usar setpreferredsize ejemplo como java swing layout-manager

setpreferredsize - set border java



¿Debo evitar el uso de los métodos de tamaño de set(Preferred | Maximum | Maximum) en Java Swing? (9)

Varias veces me han criticado por sugerir el uso de los siguientes métodos:

  1. setPreferredSize
  2. setMinimumSize
  3. setMaximumSize

en componentes Swing . No veo ninguna alternativa a su uso cuando quiero definir proporciones entre los componentes mostrados. Me han dicho esto:

Con los diseños, la respuesta es siempre la misma: use un LayoutManager adecuado

He buscado un poco en la web, pero no he encontrado ningún análisis exhaustivo del tema. Así que tengo las siguientes preguntas:

  1. ¿Debo evitar completamente el uso de esos métodos?
  2. Los métodos han sido definidos por una razón. Entonces, ¿cuándo debo usarlos? En que contexto ¿Para qué fines?
  3. ¿Cuáles son exactamente las consecuencias negativas de usar esos métodos? (Solo puedo pensar en agregar portabilidad entre sistemas con diferente resolución de pantalla).
  4. No creo que ningún LayoutManager pueda satisfacer exactamente todas las necesidades de diseño deseadas. ¿Realmente necesito implementar un nuevo LayoutManager para cada pequeña variación en mi diseño?
  5. Si la respuesta a 4 es "sí", ¿no llevará esto a una proliferación de clases de LayoutManager que será difícil de mantener?
  6. En una situación en la que necesito definir proporciones entre los hijos de un componente (por ejemplo, child1 debería usar el 10% del espacio, child2 40%, child3 50%), ¿es posible lograrlo sin implementar un LayoutManager personalizado?

¿Debo evitar completamente el uso de esos métodos?

No, no hay evidencia formal que sugiera que llamar o anular estos métodos no está permitido. De hecho, Oracle dice que estos métodos se utilizan para dar sugerencias de tamaño: http://docs.oracle.com/javase/tutorial/uiswing/layout/using.html#sizealignment .

También se pueden anular (lo que es la mejor práctica para Swing) al extender un componente Swing (en lugar de llamar al método en la instancia del componente personalizado)

Lo más importante, sin importar cómo especifique el tamaño de su componente, asegúrese de que el contenedor de su componente use un administrador de diseño que respete el tamaño solicitado del componente.

Los métodos han sido definidos por una razón. Entonces, ¿cuándo debo usarlos? En que contexto ¿Para qué fines?

Cuando necesite proporcionar sugerencias de tamaño personalizadas al administrador de diseño de contenedores para que el componente se distribuya bien

¿Cuáles son exactamente las consecuencias negativas de usar esos métodos? (Solo puedo pensar en agregar portabilidad entre sistemas con diferente resolución de pantalla).

  • Muchos administradores de diseño no prestan atención al tamaño máximo solicitado de un componente. Sin embargo, BoxLayout y SpringLayout hacen. Además, GroupLayout proporciona la capacidad de establecer el tamaño mínimo, preferido o máximo de manera explícita, sin tocar el componente.

  • Asegúrese de que realmente necesita establecer el tamaño exacto del componente. Cada componente Swing tiene un tamaño preferido diferente, dependiendo de la fuente que use y la apariencia. Por lo tanto, tener un tamaño de conjunto puede producir diferentes aspectos de la interfaz de usuario en diferentes sistemas

  • a veces se pueden encontrar problemas con GridBagLayout y los campos de texto, en donde si el tamaño del contenedor es más pequeño que el tamaño preferido, se usa el tamaño mínimo, lo que puede hacer que los campos de texto se reduzcan considerablemente.

  • JFrame no impone la sobrescritura de getMinimumSize() solo llamando a setMinimumSize(..) en sus trabajos

No creo que ningún LayoutManager pueda satisfacer exactamente todas las necesidades de diseño deseadas. ¿Realmente necesito implementar un nuevo LayoutManager para cada pequeña variación en mi diseño?

Si por implementación te refieres a usar entonces sí. No un LayoutManger puede manejar todo, cada LayoutManager tiene sus pros y sus contras, por lo que cada uno se puede usar en conjunto para producir el diseño final.

Referencia:


En una situación en la que necesito definir las proporciones entre los hijos de un componente (el niño 1 debe usar el 10% del espacio, el niño2 el 40%, el niño3 el 50%), ¿es posible lograrlo sin implementar un administrador de diseño personalizado?

Tal vez GridBagLayout satisfaría tus necesidades. Además de eso, hay un montón de administradores de diseño en la web, y apuesto a que hay uno que se adapta a sus necesidades.


  1. ¿Debo evitar completamente el uso de esos métodos?

    Sí para el código de la aplicación.

  2. Los métodos han sido definidos por una razón. Entonces, ¿cuándo debo usarlos? En que contexto ¿Para qué fines?

    No lo sé, personalmente lo considero un accidente de diseño de API. Ligeramente forzado por componentes compuestos que tienen ideas especiales sobre el tamaño de los niños. "Ligeramente", porque deberían haber implementado sus necesidades con un LayoutManager personalizado.

  3. ¿Cuáles son exactamente las consecuencias negativas de usar esos métodos? (Solo puedo pensar en agregar portabilidad entre sistemas con diferente resolución de pantalla).

    Algunas razones técnicas (incompletas, y desafortunadamente están rotas debido a la migración de SwingLabs a java.net) se mencionan, por ejemplo, en las Reglas (jeje) o en el link @bendicott que se encuentra en su comentario a mi respuesta . Socialmente, representa un montón de trabajo para su desafortunado compañero que tiene que mantener el código y tiene que localizar un diseño roto.

  4. No creo que ningún LayoutManager pueda satisfacer exactamente todas las necesidades de diseño deseadas. ¿Realmente necesito implementar un nuevo LayoutManager para cada pequeña variación en mi diseño?

    Sí, hay LayoutManagers lo suficientemente poderosos para satisfacer una muy buena aproximación a "todas las necesidades de diseño". Los tres grandes son JGoodies FormLayout, MigLayout, DesignGridLayout. Así que no, en la práctica, rara vez escribes LayoutManagers excepto en entornos simples altamente especializados.

  5. Si la respuesta a 4 es "sí", ¿no llevará esto a una proliferación de clases de LayoutManager que será difícil de mantener?

    (La respuesta a 4 es "no".)

  6. En una situación en la que necesito definir las proporciones entre los hijos de un componente (por ejemplo, el niño 1 debería usar el 10% del espacio, el niño 2 el 40%, el niño 3 el 50%), ¿es posible lograrlo sin implementar un LayoutManager personalizado?

    Cualquiera de los Big-Three puede, ni siquiera puede GridBag (nunca se molestó en dominar realmente, demasiados problemas por muy poco poder).


Algunas heurísticas:

  • No use el set[Preferred|Maximum|Minimum]Size() cuando realmente quiere reemplazar el get[Preferred|Maximum|Minimum]Size() , como se puede hacer al crear su propio componente, como se muestra here .

  • No use el set[Preferred|Maximum|Minimum]Size() cuando pueda confiar en el getPreferred|Maximum|Minimum]Size un componente, como se muestra here y a continuación.

  • Utilice el set[Preferred|Maximum|Minimum]Size() para derivar la geometría posterior a la validate() , como se muestra a continuación y here .

  • Si un componente no tiene un tamaño preferido, por ejemplo, JDesktopPane , es posible que deba dimensionar el contenedor, pero cualquier elección de este tipo es arbitraria. Un comentario puede ayudar a aclarar la intención.

  • Considere diseños alternativos o personalizados cuando encuentre que tendría que recorrer muchos componentes para obtener tamaños derivados, como se menciona en estos here .

import java.awt.Component; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.GridLayout; import java.awt.KeyboardFocusManager; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.List; import javax.swing.JComponent; import javax.swing.JDesktopPane; import javax.swing.JFrame; import javax.swing.JInternalFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.SwingUtilities; /** * @see https://.com/questions/7229226 * @see https://.com/questions/7228843 */ public class DesignTest { private List<JTextField> list = new ArrayList<JTextField>(); private JPanel panel = new JPanel(); private JScrollPane sp = new JScrollPane(panel); public static void main(String args[]) { EventQueue.invokeLater(new Runnable() { @Override public void run() { DesignTest id = new DesignTest(); id.create("My Project"); } }); } private void addField(String name) { JTextField jtf = new JTextField(16); panel.add(new JLabel(name, JLabel.LEFT)); panel.add(jtf); list.add(jtf); } private void create(String strProjectName) { panel.setLayout(new GridLayout(0, 1)); addField("First Name:"); addField("Last Name:"); addField("Address:"); addField("City:"); addField("Zip Code:"); addField("Phone:"); addField("Email Id:"); KeyboardFocusManager.getCurrentKeyboardFocusManager() .addPropertyChangeListener("permanentFocusOwner", new FocusDrivenScroller(panel)); // Show half the fields sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); sp.validate(); Dimension d = sp.getPreferredSize(); d.setSize(d.width, d.height / 2); sp.setPreferredSize(d); JInternalFrame internaFrame = new JInternalFrame(); internaFrame.add(sp); internaFrame.pack(); internaFrame.setVisible(true); JDesktopPane desktopPane = new JDesktopPane(); desktopPane.add(internaFrame); JFrame frmtest = new JFrame(); frmtest.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frmtest.add(desktopPane); frmtest.pack(); // User''s preference should be read from java.util.prefs.Preferences frmtest.setSize(400, 300); frmtest.setLocationRelativeTo(null); frmtest.setVisible(true); list.get(0).requestFocusInWindow(); } private static class FocusDrivenScroller implements PropertyChangeListener { private JComponent parent; public FocusDrivenScroller(JComponent parent) { this.parent = parent; } @Override public void propertyChange(PropertyChangeEvent evt) { Component focused = (Component) evt.getNewValue(); if (focused != null && SwingUtilities.isDescendingFrom(focused, parent)) { parent.scrollRectToVisible(focused.getBounds()); } } } }


Aquí hay muchas respuestas buenas, pero quiero agregar un poco más sobre las razones por las que normalmente debería evitarlas (la pregunta surgió nuevamente en un tema duplicado):

Con pocas excepciones, si está usando estos métodos, probablemente esté ajustando su GUI para que se vea bien en una apariencia específica (y con la configuración específica de su sistema, por ejemplo, la fuente de escritorio preferida, etc.). Los métodos en sí mismos no son intrínsecamente malos, pero las razones típicas para usarlos son . Tan pronto como comienza a ajustar las posiciones y los tamaños de píxeles en un diseño, corre el riesgo de que su GUI se rompa (o, como mínimo, se vea mal) en otras plataformas.

Como ejemplo de esto, intente cambiar el aspecto y la apariencia predeterminados de su aplicación. Incluso con las opciones disponibles en su plataforma, puede sorprenderse de lo mal que se pueden representar los resultados.

Por lo tanto, en el nombre de mantener su GUI funcional y atractiva en todas las plataformas (recuerde que uno de los principales beneficios de Java es su multiplataforma), debe confiar en los administradores de diseño, etc., para ajustar automáticamente los tamaños de sus componentes para que se representen correctamente fuera de su entorno de desarrollo específico.

Dicho todo esto, ciertamente puede concebir situaciones en las que estos métodos están justificados. Una vez más, no son intrínsecamente malvados, pero su uso suele ser una gran señal de advertencia que indica posibles problemas con la GUI. Solo asegúrese de conocer el alto potencial de complicaciones cuando las use, y siempre intente pensar si hay otra solución de apariencia independiente para sus problemas: la mayoría de las veces encontrará que estas Los métodos no son necesarios.

Por cierto, si se siente frustrado con los administradores de diseño estándar, hay muchos de terceros de código abierto, por ejemplo , FormLayout o MigLayout . Algunos constructores de GUI incluso tienen soporte integrado para administradores de diseño de terceros: el editor de GUI de WindowBuilder de Eclipse, por ejemplo, se envía con soporte para FormLayout y MigLayout .


Estos métodos son poco conocidos por la mayoría de las personas. Absolutamente no debes ignorar estos métodos. Depende del gestor de diseño si respetan estos métodos. Esta página tiene una tabla que muestra qué gestores de diseño respetan cuál de esos métodos:

http://thebadprogrammer.com/swing-layout-manager-sizing/

He estado escribiendo el código Swing durante más de 8 años y los administradores de diseño incluidos en el JDK siempre han respondido a mis necesidades. Nunca he necesitado un administrador de diseño de terceros para lograr mis diseños.

Diré que no debe intentar dar sugerencias al gestor de diseño con estos métodos hasta que esté seguro de que los necesita. Haga su diseño sin dar ninguna sugerencia de tamaño (es decir, deje que el administrador del diseño haga su trabajo) y luego puede hacer correcciones menores si es necesario.


Lo estoy viendo diferente a la respuesta aceptada.

1) ¿Debo evitar completamente el uso de esos métodos?

¡Nunca evites! Están allí para expresar las restricciones de tamaño de sus componentes al administrador de diseño. Puede evitar usarlos si no usa ningún administrador de diseño e intente administrar el diseño visual por su cuenta.

Desafortunadamente, Swing no viene con dimensiones predeterminadas razonables. Sin embargo, en lugar de establecer las dimensiones de un componente, es mejor OOP descender su propio componente con valores predeterminados razonables. (En ese caso, usted llama a setXXX en su clase descendiente). Alternativamente, puede anular los métodos getXXX para el mismo efecto.

2) Los métodos han sido definidos por una razón. Entonces, ¿cuándo debo usarlos? En que contexto ¿Para qué fines?

Siempre. Cuando cree un componente, establezca su tamaño real mínimo / preferido / máximo de acuerdo con el uso de ese componente. Por ejemplo, si tiene un JTextField para ingresar símbolos de países como el Reino Unido, su tamaño preferido será tan ancho como para que quepan dos caracteres (con la fuente actual, etc.) pero probablemente no tenga sentido dejar que crezca más. Después de todo, los símbolos de los países son dos caracteres. Al contrario, si tiene un JTextField para ingresar, p. Ej., Un nombre de cliente, puede tener un tamaño preferido para el tamaño de píxel para 20 caracteres, pero puede aumentar de tamaño si se cambia el tamaño del diseño, así que establezca el tamaño máximo en más. Al mismo tiempo, tener un JTextField ancho de 0px no tiene sentido, así que establezca un tamaño mínimo realista (yo diría que el tamaño de píxel de 2 caracteres).

3) ¿Cuáles son exactamente las consecuencias negativas de usar esos métodos?

(Solo puedo pensar en agregar portabilidad entre sistemas con diferente resolución de pantalla).

No hay consecuencias negativas. Estos son consejos para el administrador de diseño.

4) No creo que ningún LayoutManager pueda satisfacer exactamente todas las necesidades de diseño deseadas.

¿Realmente necesito implementar un nuevo LayoutManager para cada pequeña variación en mi diseño?

No, definitivamente no. El enfoque habitual es colocar en cascada diferentes gestores de disposición básicos, como la disposición horizontal y vertical.

Por ejemplo, el siguiente diseño:

<pre> +--------------+--------+ | ###JTABLE### | [Add] | | ...data... |[Remove]| | ...data... | | | ...data... | | +--------------+--------+ </pre>

Está teniendo dos partes. Las partes izquierda y derecha son un diseño horizontal. La parte derecha es un JPanel agregado al diseño horizontal, y este JPanel tiene un diseño vertical que establece los botones verticalmente.

Por supuesto, esto puede volverse complicado con un diseño de la vida real. Por lo tanto, los administradores de diseño basados ​​en cuadrícula como MigLayout son mucho mejores si están a punto de desarrollar algo serio.

5) Si la respuesta a 4 es "sí", ¿no llevará esto a una proliferación de clases de LayoutManager que será difícil de mantener?

No, definitivamente no debe desarrollar gestores de diseño, a menos que necesite algo muy especial.

6) En una situación en la que necesito definir proporciones ...

entre los hijos de un componente (p. ej., child1 debería usar el 10% del espacio, child2 40%, child3 50%), ¿es posible lograrlo sin implementar un LayoutManager personalizado?

Básicamente, una vez que se ajustan correctamente los tamaños preferidos, es posible que no desee hacer nada en porcentaje. Simplemente, porque los porcentajes son inútiles (por ejemplo, no tiene sentido tener un JTextField del 10% del tamaño de la ventana, ya que uno puede reducir la ventana para que JTextField tenga un ancho de 0px, o puede expandir la ventana para que JTextField esté en dos pantallas en una configuración de múltiples pantallas).

Sin embargo, muchas veces puede usar los porcentajes para controlar el tamaño de bloques de construcción más grandes de su interfaz gráfica de usuario (paneles, por ejemplo).

Puede usar JSplitPane donde puede preestablecer la proporción de los dos lados. O bien, puede usar MigLayout, que le permite establecer dichas restricciones en porcentaje, píxeles y otras unidades.


Si tiene problemas con los diseños en Java Swing, puedo recomendar el FormLayout de FormLayout proporciona gratuitamente como parte de la biblioteca de software gratuito de Forms de Karsten Lentzsch aquí .

Este popular gestor de diseño es extremadamente flexible, lo que permite el desarrollo de interfaces de usuario Java muy pulidas.

Encontrará la documentación de Karsten here , y una documentación bastante buena de eclipse here .


¿Debo evitar completamente el uso de esos métodos? Yo no diría "evitar" a ellos. Yo diría que si crees que los necesitas, probablemente estés haciendo algo mal. Los tamaños de los componentes se determinan en contexto. Por ejemplo, los tamaños de los componentes de texto están determinados por el número de filas y columnas que especifique, combinadas con la fuente que haya elegido. El tamaño de su botón y etiqueta será el tamaño del gráfico, si establece uno, o el espacio necesario para mostrar el texto que establece. Cada componente tiene un tamaño natural, y los administradores de diseño los usarán para distribuir todo sin que usted necesite especificar tamaños. La principal excepción es el JScrollPane, que tiene un tamaño independiente de lo que contiene. Para esos, a veces llamaré a setSize() , y dejaré que ese tamaño determine el tamaño inicial de la ventana, llamando a JFrame.pack() . Por lo general, dejaré que el tamaño de la ventana determine el tamaño de JScrollPane. El usuario determinará el tamaño de la ventana. Muchos administradores de diseño ignoran los tamaños que configuras de todos modos, por lo que a menudo no hacen mucho bien.

Los métodos han sido definidos por una razón. Entonces, ¿cuándo debo usarlos? En que contexto ¿Para qué fines? Creo que se agregaron para proporcionar sugerencias a los administradores de diseño. Es posible que se hayan escrito por razones históricas, porque los administradores de diseño eran nuevos y la gente no confiaba plenamente en ellos. Conozco a unos pocos desarrolladores que evitaron los gestores de diseño y colocaron todo manualmente, solo porque no querían molestarse en aprender un nuevo paradigma. Es una idea terrible.

¿Cuáles son exactamente las consecuencias negativas de usar esos métodos? (Solo puedo pensar en agregar portabilidad entre sistemas con diferente resolución de pantalla). Son ineficaces y producen malos diseños, con objetos que se aprietan o estiran a tamaños no naturales. Y los diseños serán frágiles. Los cambios en el tamaño de la ventana a veces rompen el diseño y ponen las cosas en lugares equivocados.

No creo que ningún LayoutManager pueda satisfacer exactamente todas las necesidades de diseño deseadas. ¿Realmente necesito implementar un nuevo LayoutManager para cada pequeña variación en mi diseño? No debe "implementar" un nuevo LayoutManager. Debes instanciar los existentes. A menudo utilizo varios gestores de diseño en una sola ventana. Cada JPanel tendrá su propio gestor de diseño. Algunas personas rechazan los diseños anidados, porque son difíciles de mantener. Cuando los uso, le doy a cada uno su propio método de creación para que sea más fácil ver lo que hace cada uno. Pero nunca "implemento" un gestor de diseño. Yo sólo los instalé.

Si la respuesta a 4 es "sí", ¿no llevará esto a una proliferación de clases de LayoutManager que será difícil de mantener? Si está implementando nuevas clases de administrador de diseño para pequeñas variaciones en el diseño, las está utilizando mal. Si solo estás implementando nuevos administradores de diseño, probablemente estés haciendo algo mal. La única vez que extendí una clase LayoutManager, fue para agregar un control deslizante de zoom a un JScrollPane.

En una situación en la que necesito definir proporciones entre los hijos de un componente (por ejemplo, child1 debería usar el 10% del espacio, child2 40%, child3 50%), ¿es posible lograrlo sin implementar un LayoutManager personalizado? JSplitPane tiene una forma de especificar el porcentaje que debe obtener cada componente. El divisor se puede mover de forma predeterminada, pero puede desactivarlo si lo desea. No uso mucho esa característica. Normalmente tengo algunos componentes que ocupan un tamaño determinado, y el resto del espacio está ocupado por un panel de desplazamiento. El tamaño del panel de desplazamiento se ajustará con el tamaño de la ventana. Si tiene dos paneles de desplazamiento uno al lado del otro, puede colocarlos en un JSplitPane y especificar el porcentaje de espacio nuevo asignado a cada uno a medida que el usuario expande y contrae las ventanas.