¿Debo evitar el uso de métodos set (Preferidos | Máximos | Mínimos) en Java Swing?

481

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

  1. setPreferredSize
  2. setMinimumSize
  3. setMaximumSize

en Swingcomponentes. 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. Entonces tengo las siguientes preguntas:

  1. ¿Debo evitar por completo 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 que 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í", ¿esto no conducirá a una proliferación de clases LayoutManager que será difícil de mantener?
  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?
Heisenbug
fuente

Respuestas:

236
  1. ¿Debo evitar por completo 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 que fines?

    No sé, personalmente lo considero un accidente de diseño de API. Ligeramente forzado por componentes compuestos que tienen ideas especiales sobre tamaños de 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).

    Algunos (incompletos, y desafortunadamente los enlaces están rotos debido a la migración de SwingLabs a java.net), por ejemplo, las razones técnicas se mencionan en las Reglas (jeje) o en el enlace @bendicott que se encuentra en su comentario a mi respuesta . Socialmente, presentando toneladas de trabajo a su desafortunado compañero que tiene que mantener el código y tiene que rastrear 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 potentes como para satisfacer una muy buena aproximación a "todas las necesidades de diseño". Los tres grandes son JGoodies FormLayout, MigLayout, DesignGridLayout. Entonces, no, en la práctica, rara vez escribe LayoutManagers, excepto en entornos simples altamente especializados.

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

    (La respuesta a 4 es "no".)

  6. En una situación en la que necesito definir proporciones entre los hijos de un Componente (por ejemplo, el niño 1 debe usar el 10% del espacio, el niño 2 40%, el niño 3 50%), ¿es posible lograr eso 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 poca potencia).

kleopatra
fuente
44
No estoy completamente seguro de estar de acuerdo con este consejo en al menos dos situaciones. 1) Componentes renderizados personalizados 2) Uso de a JEditorPanecon HTML que no sugiere por sí mismo un ancho. OTOH No estoy seguro si me he perdido algo. Revisaré cuidadosamente las respuestas en el hilo, pero estaba interesado si tenía algún comentario, particularmente sobre el último caso.
Andrew Thompson
2
@Andrew Thompson 1) compilaciones personalizadas: es la compilación en sí la responsable de devolver sugerencias de diseño útiles, si no implican errores, 2) incluso las compilaciones centrales tienen errores ;-) 3) No me importa el espacio en blanco (aunque no fue esta vez intencional, gracias :-)
kleopatra
8
No puedo creer que la respuesta aceptada sea la que dice evitar usar los métodos setXXX (). A veces, simplemente los necesita para proporcionar una pista al administrador de diseño. Si está diseñando un panel, entonces debe sentirse absolutamente libre de usar estos métodos cuando sea necesario. Dicho esto, creo que si usa el administrador de diseño apropiado, encontrará que no necesita estos métodos con mucha frecuencia, pero en ocasiones simplemente los necesita. Intente colocar un JComboBox o JSpinner en un X_AXIS BoxLayout y no los use, cree que encontrará que necesita setMaximumSize () allí.
Michael
55
@Michael no, no lo necesito absolutamente: la respuesta siempre es usar un LayoutManager decente y hacer ajustes precisos en el nivel de administrador (frente al nivel de componente)
kleopatra
55
Sigue diciendo "use un LayoutManager decente y dígale qué tamaños desea" en todo stackoverflow, pero nunca da ejemplos específicos de un LayoutManager "decente". Y ninguno de los gerentes estándar permite controlar los tamaños directamente.
Ti Strga
100

Algunas heurísticas:

  • No lo use set[Preferred|Maximum|Minimum]Size()cuando realmente quiera anular get[Preferred|Maximum|Minimum]Size(), como podría hacerse al crear su propio componente, como se muestra aquí .

  • No use set[Preferred|Maximum|Minimum]Size()cuando podría confiar en que un componente se anule cuidadosamente getPreferred|Maximum|Minimum]Size, como se muestra aquí y a continuación.

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

  • Si un componente no tiene un tamaño preferido, por ejemplo JDesktopPane, puede que tenga que cambiar el tamaño del contenedor, pero cualquier elección es arbitraria. Un comentario puede ayudar a aclarar la intención.

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

ingrese la descripción de la imagen aquí

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 /programming/7229226
 * @see /programming/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());
            }
        }
    }
}
trashgod
fuente
2
no estoy de acuerdo (como habrás adivinado :-) con el razonamiento por "factores externos": las propiedades XXSize están destinadas a expresar solo las necesidades internas . Ajustar los del exterior es mal uso, también conocido como pirateo. Si desea un marco (interno o J-) con un tamaño específico en relación con su preferencia ... dimensione el marco, no el contenido
kleopatra
2
@kleopatra: solo para ser un poco insistente: si los métodos setXXSize nunca se deben usar desde afuera, ¿por qué no se han declarado privados o protegidos? ¿No es esto una falta de diseño? ¿El modificador público no le dice implícitamente al usuario que puede usar esos métodos?
Heisenbug
2
Tengo que estar de acuerdo con @kleopatra: setPreferredSize()siempre reemplaza el cálculo del componente con una elección arbitraria.
trashgod
1
@trashgod +100 para ti Creo que no hay ningún problema con anular estos métodos, incluso llamarlos (pero, por supuesto, esto significaría que tienes un componente personalizado, por lo que anular sería mejor)
David Kroukamp
55
@DavidKroukamp: Gracias. Me refiero a la mayor experiencia de kleopatra, pero veo el valor de examinar críticamente la opinión contraria.
trashgod
47

¿Debo evitar por completo 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 pistas sobre el tamaño: http://docs.oracle.com/javase/tutorial/uiswing/layout/using.html#sizealignment .

También pueden anularse (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, independientemente de cómo especifique el tamaño de su componente, asegúrese de que el contenedor de su componente utilice 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 que 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, BoxLayouty SpringLayouthacer. Además, GroupLayoutproporciona la capacidad de establecer el tamaño mínimo, preferido o máximo explícitamente, 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 usa y el aspecto. Por lo tanto, tener un tamaño establecido puede producir una apariencia variada de la interfaz de usuario en diferentes sistemas

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

  • JFrameno impone anulación getMinimumSize()solo invocando setMinimumSize(..)sus obras

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 implementar te refieres a usar, entonces sí. No se LayoutMangerpuede manejar todo, cada uno LayoutManagertiene sus pros y sus contras, por lo que se pueden usar juntos para producir el diseño final.

Referencia:

David Kroukamp
fuente
3
proporcionar sugerencias de tamaño personalizadas que es una contradicción en sí misma: proporcionar sugerencias de tamaño (¡en px!) es la tarea exclusiva del componente. Los calcula en función de los detalles internos del estado que ninguna otra parte, excepto sí misma, puede conocer (ni puede realizar un seguimiento). Desde la perspectiva del cliente, los medios de personalización pueden ser un LayoutManager adecuado y / o una API especializada en el componente que permite configurar los requisitos de tamaño en términos de propiedades "semánticas" relevantes para el tamaño, número de filas / columnas en un componente de texto
kleopatra
3
@kleopatra Todavía me gustaría saber por qué Oracle nos dice cómo usar estos métodos y la forma correcta de usarlos. Es posible que tengamos nuestras propias preferencias, pero no podemos decir que los diseñadores dicen que no se utilizará cuando no haya evidencia que sugiera esto. Pero es por eso que ofrecí la recompensa, tal vez si atraería a otros que podrían brindar información de una fuente creíble donde Oracle orquesta no usar estos métodos (por lo tanto, es una mala práctica si lo hace, por ejemplo, setMinimumSize tiene que ser llamó a cosas como JSplitPane, etc., esto se puede ver en el tutorial de Oracle de paneles divididos.
David Kroukamp
44
@David: He llegado a ver los setXxxSizemétodos como una señal de alerta que podría terminar aquí , incluso cuando los documentos lo sugieran. Yo casi siempre debería haber anulado getXxxSize, donde se tiene acceso a la geometría requerida; e incluso ejemplos cortos se reciclan más de lo que quiero pensar. +1 por mencionar la variación entre los administradores de diseño y citar el tutorial.
trashgod
1
Oh, en mi comentario anterior, quise citar la respuesta aquí .
trashgod
13
+1 "No, no hay evidencia formal que sugiera que llamar o anular estos métodos no esté permitido". Correcto. La publicación etiquetada como respuesta es BS simple.
TT.
25

Aquí hay muchas buenas respuestas, 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á utilizando estos métodos, probablemente esté ajustando su GUI para que se vea bien en un aspecto específico (y con la configuración específica de su sistema, por ejemplo, su fuente de escritorio preferida, etc.). Los métodos en sí mismos no son intrínsecamente malos, pero las razones típicas para usarlos sí lo son . Tan pronto como comience a ajustar las posiciones y 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 predeterminado de su aplicación. Incluso solo con las opciones disponibles en su plataforma, puede sorprenderse de lo mal que se pueden presentar los resultados.

Entonces, en nombre de mantener su GUI funcional y agradable en todas las plataformas (recuerde, 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 represente 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 es normalmente una gran señal de alerta que indica posibles problemas de GUI. Solo asegúrese de estar al tanto del alto potencial de complicaciones si / cuando las usa, y siempre trate de pensar si hay otra solución independiente de la apariencia y la sensación para sus problemas; la mayoría de las veces encontrará que estos Los métodos no son necesarios.

Por cierto, si te sientes frustrado con los administradores de diseño estándar, hay muchos otros buenos y gratuitos de código abierto de terceros, por ejemplo, JGoodies 'FormLayout o MigLayout. Algunos constructores de GUI incluso tienen soporte incorporado para administradores de diseño de terceros: el editor de GUI WindowBuilder de Eclipse, por ejemplo, se entrega con soporte para FormLayouty MigLayout.

Jason C
fuente
2
+1 una respuesta considerada: simplemente no estoy de acuerdo con que no sean intrínsecamente malvados simplemente porque son :-) Por lo general, los clientes externos no tienen ninguna posibilidad de adivinar, y las meras suposiciones son lo más cercanas que pueden estar las personas externas: pistas de diseño medio correctas: solo los componentes en sí tienen toda la información en todo momento para devolver cualquier cosa útil. Y desde el momento en que los extraños interfieren, es su responsabilidad mantener esos consejos actualizados que no pueden.
kleopatra
1
Bueno, ya sabes, tengo una visión más de "las armas no matan a la gente, la gente mata a la gente" de este tipo de cosas. :) Si alguien usa estos métodos, debe estar al tanto de cosas como los buenos puntos que plantea sobre el uso impredecible de las sugerencias de diseño (es por eso que las situaciones en las que estos métodos son apropiados son realmente raros).
Jason C
Creo que establecer el tamaño preferido no es una gran bandera roja en absoluto. No establecerlo es una gran bandera roja en su lugar. Déjame elaborar. El administrador de diseño, no importa cuán inteligente sea, no tiene idea de la función lógica de un widget gui. Por ejemplo, el administrador de diseño no puede distinguir entre un JTextField para ingresar el código postal y un JTextField para ingresar un nombre. Del mismo modo, no puede distinguir entre un botón de herramienta junto a un JTextField o un gran botón Aceptar en la parte inferior de un formulario. Por lo tanto, se necesita un mejor conjunto de widgets o se necesitan algunas sugerencias de tamaño, ¿no?
Gee Bee
@GeeBee No, ese es un excelente ejemplo de una bandera roja, de hecho. Lo que debe hacer es usar JTextField.setColumnspara establecer el recuento de columnas, que ajusta el tamaño preferido en consecuencia. Si lo hace, setPreferredSizeentonces está codificando un tamaño, lo que romperá sus diseños según el tamaño de fuente de la plataforma. Aquí hay algunos campos de texto en un diseño de bolsa de cuadrícula con setColumnsllamadas apropiadas . Para sus botones, use diseños / pesos de cuadrícula apropiados para controlar los tamaños.
Jason C
@GeeBee Y ahora, con eso hecho correctamente, observe cómo disminuyen los anchos del campo de texto cuando disminuyo el tamaño de fuente: i.snag.gy/ZULulh.jpg . Incluso cambiar el tamaño de la fuente sobre la marcha ahora funciona automáticamente, en lugar de que usted, por ejemplo, tenga que recalcular todos los anchos de campo de texto y llamar explícitamente a setPreferredSize nuevamente para cada uno, todo lo que tiene que hacer es invalidar el diseño y sus tamaños se ajustarán.
Jason C
20

Si tiene problemas con los diseños en Java Swing, le recomiendo encarecidamente los JGoodies FormLayoutque Karsten Lentzsch proporciona gratuitamente como parte de la biblioteca gratuita de formularios de aquí .

Este administrador de diseño muy popular es extremadamente flexible, lo que permite desarrollar interfaces de usuario Java muy pulidas.

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

Tom
fuente
16

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

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

He estado escribiendo código Swing durante más de 8 años y los gerentes 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 tratar de dar pistas al administrador de diseño con estos métodos hasta que esté seguro de que los necesita. Realice su diseño sin dar ninguna sugerencia de tamaño (es decir, deje que el administrador de diseño haga su trabajo) y luego puede hacer correcciones menores si es necesario.

Miguel
fuente
1
o hay un ligero malentendido (de su parte) o un malentendido (de mi parte), elija :-) Sigue repitiendo (aquí, en su blog, en su respuesta relacionada con BoxLayout) el conjunto XXSize como importante, en realidad el LayoutManager está (o no) interesado en el XXSize, esa es la sugerencia de tamaño independiente de cómo surgió (cálculo interno por el componente o forzado manualmente por el código de la aplicación)
kleopatra
1
No estoy seguro de entender lo que estás haciendo aquí. Menciono anteriormente que los métodos XXSize () son solo sugerencias. Realmente no veo nada de malo en darle una pequeña pista al administrador de diseño, si es necesario. En mi código de swing, encontrarás un método setXXSize () ocasional. No muchos, pero de vez en cuando encuentro que son necesarios. JComboBox y JSpinner con frecuencia necesitan sugerencias. Especialmente un JComboBox que se completa después de que se realiza. Parece que estás en contra de cualquier uso de estos métodos y no sé por qué. (Tal vez yo soy el que falta el barco en esto, supongo).
Michael
55
no los métodos son las sugerencias, las propiedades son: los componentes deben informar algo razonable para todas las sugerencias, algunos (como fi JComboBox) no lo hacen, al devolver maxInteger más o menos. Eso es un error y debe ser reparado por el combo. En cuanto a su hábito: asegúrese de estar lejos cuando el encargado del mantenimiento tenga que limpiar eso :) Las sugerencias codificadas tienden a arruinar el diseño al menor cambio y son difíciles de detectar como la razón de un diseño roto.
kleopatra
15

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

Quizás GridBagLayoutsatisfarí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 ajusta a sus requisitos.

Thomas
fuente
gracias por la respuesta. Debo suponer que también quisiste decir: "no uses setPreferredSize en absoluto", ¿verdad?
Heisenbug
1
GridBagLayout usa restricciones, donde puede especificar el "peso" tanto en X como en Y para un componente dado, de modo que LayoutManager puede decidir qué hacer con el espacio adicional en un cambio de tamaño. PERO aún necesita / puede usar setPreferredSize para determinar el tamaño preferido de cada componente, tenga en cuenta que "preferido" no significa que siempre se respetará. Para casos especiales, también puede necesitar setMinimumSize y setMaximumSize de todos modos. No son malvados , no compren eso. docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html
マ ル ち ゃ ん だ よ
5

Lo veo diferente a la respuesta aceptada.

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

¡Nunca lo evites! Están allí para expresar las restricciones de tamaño de sus componentes al administrador de diseño. Puede evitar usarlos si no está usando 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 que OOP descienda su propio componente con valores predeterminados razonables. (En ese caso, llama a setXXX en su clase descendiente). Alternativamente, puede anular los métodos getXXX para obtener el mismo efecto.

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

Siempre. Cuando cree un componente, establezca su tamaño mínimo / preferido / máximo realista de acuerdo con el uso de ese componente. Por ejemplo, si tiene un JTextField para ingresar símbolos de país como el Reino Unido, su tamaño preferido será tan ancho como para caber 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 país son dos caracteres. Por el contrario, si tiene un JTextField para ingresar, por ejemplo, el nombre de un cliente, puede tener un tamaño preferido como el tamaño de píxel para 20 caracteres, pero puede crecer hasta ser más grande si se cambia el tamaño del diseño, así que configure el tamaño máximo en más. Al mismo tiempo, tener un JTextField de 0px de ancho 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).

Sin consecuencias negativas. Estas son sugerencias 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 poner en cascada diferentes gestores de diseño básicos, como el diseño horizontal y vertical.

Por ejemplo, el diseño a continuación:

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

tiene 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 presenta 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á a punto de desarrollar algo serio.

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

No, definitivamente no deberá desarrollar administradores 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 lograr eso sin implementar un LayoutManager personalizado?

Básicamente, una vez que los tamaños preferidos se configuran correctamente, es posible que no desee hacer nada en porcentaje. Simplemente, porque los porcentajes no tienen sentido (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 0px de ancho, o puede expandir la ventana para que JTextField esté en dos pantallas en un configuración de pantallas múltiples).

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

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

Gee Bee
fuente
De Verdad? Esto fue a 0? Esto es mejor que la respuesta aceptada que tiene más de 100 ups. Eso básicamente dice "¡No usarás setPreferredSize!" que es TERRIBLE En mi línea de trabajo, hay MUCHOS requisitos de tamaño específico, como "Los botones en las pantallas táctiles deben estar [X] por [Y] con un espacio [M] x [N] entre" requisitos de seguridad. btnBar.setPreferredSize( dimTouchBtn );Es la mejor manera de hacerlo. Directo, sin necesidad de un administrador de diseño personalizado. Utilizo principalmente GridBagLayoutcon algunos BorderLayouty BoxLayout, anidando cuando es conveniente. Esta es una combinación fuerte y fácil de usar.
Loduwijk
Fui apresurado en mi comentario anterior. Esta fue la primera respuesta que vi después de la respuesta aceptada. ¿Por qué SO ya no ordena por votación? Pensé que esa era una de las razones principales para el conteo de votos originalmente. Sin embargo, todavía mantengo el comentario original; Esta es una de las mejores respuestas. Excepto por su punto # 6, ese no es tan bueno. Hay muchas razones (la minoría puede ser una gran cantidad) de razones para cambiar el tamaño, y GridBagLayout lo admite bien en la mayoría de los casos que he tenido.
Loduwijk
Creo que cambiar el tamaño frente a no cambiar el tamaño no se tratará como una decisión religiosa. Hay casos de uso en los que nadie quiere cambiar el tamaño de nada, por ejemplo, si desarrolla una GUI para un quiosco, con una resolución fija preestablecida. Si tiene objetivos diferentes, como pantallas HMI industriales y el caso de "botones", entonces sí, debe tener al menos 1 cm por 1 cm para un botón en una pantalla táctil. En este caso, el DPI de la pantalla establece cómo cambiar el tamaño. Es posible que otras entradas, como los campos de texto, no cambien de tamaño verticalmente y, a veces (como un código postal), el cambio de tamaño horizontal tampoco tiene sentido.
Gee Bee
0

¿Debo evitar por completo el uso de esos métodos? Yo no diría "evitarlos". 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 la cantidad 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 configura uno, o el espacio necesario para mostrar el texto que configuró. Cada componente tiene un tamaño natural, y los administradores de diseño los usarán para diseñar todo sin necesidad de especificar tamaños. La excepción principal es JScrollPane, que tiene un tamaño independiente de lo que contenga. Para aquellos, a veces llamaré setSize(), y dejaré que ese tamaño determine el tamaño inicial de la ventana, llamandoJFrame.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 configura 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 que fines? Creo que se agregaron para proporcionar pistas a los gerentes 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 algunos desarrolladores que evitaron los administradores 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 diseños malos, con objetos que se exprimen 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 colocan las cosas en los 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. Debe crear instancias de las existentes. A menudo uso varios administradores de diseño en una sola ventana. Cada JPanel tendrá su propio administrador de diseño. Algunas personas se resisten a los diseños anidados, porque son difíciles de mantener. Cuando los uso, les 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 administrador de diseño. Yo solo los instancia.

Si la respuesta a 4 es "sí", ¿no conducirá esto a una proliferación de clases LayoutManager que será difícil de mantener? Si está implementando nuevas clases de administrador de diseño para ligeras variaciones en el diseño, las está usando mal. Si solo está implementando nuevos administradores de diseño, probablemente esté haciendo algo mal. La única vez que extendí una clase de 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 (p. Ej., 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 es móvil de forma predeterminada, pero puede desactivarlo si lo desea. No uso mucho esa función. Por lo general, tengo algunos componentes que ocupan un tamaño establecido, y el resto del espacio lo ocupa 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.

Miguel Muñoz
fuente