2009-01-30 6 views
34

Estoy escribiendo una GUI para una aplicación que usa Swing, y en interés del mantenimiento y la legibilidad del código, deseo seguir un patrón consistente en todo el sistema.¿Cuáles son sus mejores patrones y sugerencias de diseño de Swing?

La mayoría de los artículos y libros (o al menos secciones de libros) que he leído parecen proporcionar muchos ejemplos sobre cómo crear y organizar varios componentes, pero ignoran la imagen más grande de escribir una GUI completa.

¿Cuáles son sus mejores consejos para el diseño de la GUI de la aplicación y qué patrones sigue cuando diseña o refactoriza una aplicación GUI?

+0

Aquí están mis cuatro babys: http://blue-walrus.com/swing-design-patterns/ –

Respuesta

14

Utilice los administradores de diseño. Quizás piense que es más sencillo simplemente posicionar todo con posiciones codificadas ahora (especialmente si usa una herramienta de diseño gráfico), pero cuando llega el momento de actualizar la interfaz gráfica o internacionalizarla, sus sucesores lo odiarán. (Confía en mí en esto, yo era el tipo que decía usar los administradores de diseño desde el principio, y el sucesor del tipo que me ignoró).

14

Evita el uso de diseñadores de diseño de GUI (constructores). Más tarde, hará que su código sea mucho más limpio y fácil de mantener.

+1

Es cierto que si usted comienza su interfaz gráfica de usuario con un constructor, que son más o menos comprometido con el uso que el formador de largo toda la vida de la GUI. Esto es a veces aceptable, a veces no. – Eddie

+0

Sí, es cierto. Diferentes constructores almacenan metadatos en diferentes formatos que no son mutuamente compatibles. La única excepción es Instantiations Swing Designer, que funciona con el código directamente. Todos ellos crean código que no está destinado a ser editado a mano (no se puede leer) y que luego lo morderá. – Marko

+2

No estoy de acuerdo. Si conoce bien a Swing, cualquier código generado por un constructor de GUI será lo suficientemente legible. El problema es que al usar un constructor de GUI no conocerás bien a Swing. Una buena separación es, por supuesto, necesaria. – willcodejavaforfood

7

Acostúmbrate a hacer que tus devoluciones generen hilos para hacer el trabajo real, y entonces no tendrás GUIs congeladas cuando una de tus callbacks se convierta en un monstruo que consume mucho tiempo.

+1

Mejor aún, use SwingWorker. – Marko

+1

Sí, SwingWorker es una de las muchas maneras de engendrar un hilo. –

+1

No olvide SwingUtilities invocador más tarde si ese hilo necesita actualizar la GUI después :) – willcodejavaforfood

4

Definitivamente coloque la GUI en una clase y la lógica en otra clase o múltiples clases, en la mayor medida posible. Si usa el patrón MVC (Model-View-Controller), esto sucederá automáticamente. Si no lo hace, la GUI se volverá inmanejablemente complicada.

5

Trate de no codificar el texto en su aplicación. Las guiones de Swing pueden escribirse fácilmente para que sean controladas por datos, considere definir su GUI en un archivo xml (incluidos los nombres de los componentes y los atributos de posición/diseño).

Trabajé en sistemas que tenían MUCHAS hojas de propiedad (que son simplemente montones de controles, página tras página de ellas) - sin hacerlo manejado por datos, es prácticamente imposible de mantener o internacionalizar.

Si decide utilizar un constructor de GUI, nunca modifique el código que genera si es posible evitarlo, es mejor vincularse a la GUI de una clase externa. Piense en lo que sucederá si tiene que hacerlo sin el constructor: ¿será difícil trasladarlo? ¿Imposible?

Entender los aspectos críticos en swing - modificando solamente los componentes GUI de la rosca AWT, volviendo el hilo AWT lo más rápidamente posible (generar un nuevo subproceso si tiene que hacer cualquier cosa que se hace cargo de 100 ms),

Try Lo mejor para mantener su código SECO - Puede ser un verdadero desafío de programación con las GUIs de Swing - Una vez más, el código manejado por datos es la única forma que he encontrado para no repetir código constantemente como nuevo JButton ("...") ;

Si sus datos se basan en hojas de propiedades, considere seriamente crear un mecanismo de enlace para vincular sus controles a sus datos. Un buen objetivo para el código DRY sería 0 (CERO) líneas de código específicas del control por control para obtener un fragmento de datos de su base de datos a su GUI, haga que el usuario lo edite y lo devuelva a su base de datos. Esto significa que debe poder agregar un nuevo control al no hacer nada más que modificar sus datos.

8

Esta es una respuesta de alto nivel más abstracta acerca de lo que representa su GUI, no la mecánica de la misma ..

Dependiendo de su tarea, puede ser un poco difícil hacerlo para que su usuario pueda captar conceptualmente lo que está haciendo la GUI. He realizado un trabajo bastante complicado que involucra GUI, y mis enfoques más exitosos han sido aquellos que tomaron un conjunto complejo de controles y los colocaron en un diseño que el usuario esperaba.

Por ejemplo, escribí un sistema para administrar 2 dispositivos uno en cada extremo de una línea T1 (algo así como módems). Los controles eran realmente difíciles de comprender, campos como "crear loopback, probar señales de extremo lejano, probar patrones de bits cercanos al final, enviar varios patrones de bits, ..." (esto es una simplificación excesiva, era mucho peor que esto)

Tenía que entender realmente el problema, así que fui a un representante de soporte técnico que ayudó a los clientes con este problema todo el tiempo. Me mostró un diagrama en el manual y me explicó qué hicieron los diferentes controles en ese diagrama.

Tomé el diagrama, lo recreé utilizando gráficos (solo un simple dibujo de líneas en su mayor parte, pero mostró los dos extremos y las conexiones entre ellos), luego utilicé las regiones de los gráficos para representar controles Y comentarios (cambios de color) Se podía ver visualmente que se estaba emitiendo una señal. Cuando encendiste un loopback en el otro extremo, pudiste ver que la línea conectaba la señal a su línea de salida, luego podías ver el cambio de color a medida que tu extremo cercano comenzaba a obtener el patrón que estaba enviando era otra línea .

Los "Controles" fueron significativamente más intrincados que esto, pero la GUI lo redujo EXACTAMENTE a lo que el cliente necesitaba para comprender el problema.

Después de esto, tuvimos clientes que volvían a nosotros diciéndonos que nunca antes habían podido descifrar esto, ¡pero ahora lo entienden totalmente!

Esta presentación fue infinitamente más importante que el cableado de la implementación de la GUI.

3

Eche un vistazo a API de marco de aplicación (y . Es una gran API para construir su aplicación de swing, por ejemplo: todos los estilos (color, fuente, iconos ...) se definen en un archivo de configuración simple. .

18

Nunca derivar de JDialog, JFrame o JInternalFrame para definir sus formas, diálogos ...

derivan más bien de JPanel Esto le traerá las ventajas siguientes aparatos:

  • posibilidad de cambio posterior de una JFrame a un JDialog por ejemplo (porque el usuario cambió de opinión)
  • puede reutilizar una instancia de panel de un JDialog a otro (JDialog generalmente no son reutilizables porque están construidos con una referencia a su "principal", un marco u otro cuadro de diálogo)
  • puede cambiar más adelante reemplazar JDialog con una subclase más funcional de un marco de terceros.
+0

Junto con esto, definiría una interfaz de 'vista'. – willcodejavaforfood

+0

¿Qué debería hacer tu interfaz 'ver'? – Mot

4

Se supone que no debes extender las clases JFrame, JDialog, JPanel, JButton, Janything (aunque ciertas extensiones del comportamiento de la tabla solo están disponibles si lo extiendes). Puede extender JComponent si desea hacer un componente personalizado. Si se supone que deben implementar modelos (por ejemplo, extendiendo modelos abstractos), oyentes (por ejemplo, ampliando adaptadores), pero eso es todo. No necesita/tiene que extender los componentes de oscilación por lo general, y es mejor que no lo haga, ya que hace que su código esté ligado a la implementación de la superclase.

6

Evite heredar cuando la composición sea más fácil.

Por ejemplo he visto muy parecido a esto:

public class CustomerSupportApp extends JFrame { 
    JList<Customer> customers; 
    OtherBusinessComponent importantComponent; 

    etc. etc 

} 

Esta es la mezcla de lógica de negocio con la presentación. Solo hace cambios de difíciles a imposibles.

Mejor es:

public class CustomerSupportApp { 
    JList<Customer> customers; 
    OtherBusinessComponent importantComponent; 
    // The app HAS-A frame but not IS-A frame 
    JFrame frame; 
    etc. etc 
} 
+0

En su caso, es obvio, porque application! = Frame, pero hay otros ejemplos, p. 'FooFrame extiende BarFrame', donde la herencia tampoco es apropiada, p. porque tienen demasiado menos en común. – Mot

8

Evitar el desove demasiadas hebras cuando el usuario hace clic en los botones de acción varias veces. Desactive el botón al primer clic, genere su acción en el hilo de fondo y, cuando termine, vuelva a habilitar el botón. Esto puede no ser un problema para tareas de ejecución corta.

1

Creo que el principal problema al que te enfrentarás es la capacidad de prueba de tu aplicación de interfaz gráfica de usuario.

Por lo que respecta a la facilidad de mantenimiento y pruebas de unidad Me inclino por la expresión "Presentador primero" en lugar de Model View Controller (MVC) y otras derivadas que le indican que tenga la vista de la lógica de aplicación (Modelo). El mejor recurso es el web site del grupo que lo introdujo como un pensamiento.

Dado que el uso de un enfoque como este va a tomar un montón de código repetitivo para inicializar los diversos elementos de su aplicación, también sugeriría usar un marco de inyección de dependencia. Me he conformado con Guice.

9

Creo que un buen conocimiento práctico de concurrencia a menudo es subestimado. Realmente necesita familiarizarse con la política de enhebrado de Swing y las técnicas generales de sincronización para construir una GUI receptiva y un back-end eficiente.

6

Haga un uso intensivo del patrón MVC. Aquí está un ejemplo sencillo de lo que quiero decir:

class Person 
{ 
    String firstName; 
    String lastName; 
    // and getters and setters... 
} 

class PersonSwingModel 
{ 
    private Person person; 
    private javax.swing.text.PlainDocument firstName; 
    private javax.swing.text.PlainDocument lastName; 
    // and getters and setters... 
    // Create some method like init() that initializes PlainDocument values 
    // to attributes in model. 
} 

class SavePersonAction extends AbstractAction 
{ 
    private PersonSwingModel model; 
    // and getters and setters... 
} 

class PersonSwingView extends JFrame 
{ 
    private PersonSwingModel model; 
    private javax.swing.JTextField firstName; 
    private javax.swing.JTextField lastName; 
    private SavePersonAction savePersonAction; // hook up to JButton/JMenuItem 
    // and getters and setters... 
    // Create some method like init() which binds PlainDocument to JTextField 
    // and Actions to JButtons or JMenuItems 
} 

veo que algunas personas no están de acuerdo con la extensión de JFrame o JPanel. Yo no. Funciona para mi.

Además, utilice LayoutManagers. GridBagLayout es muy poderoso. Si lo usa, defina algunas constantes GridBagConstraints (como LABEL_GBC y FIELD_GBC) y continúe reutilizándolas.

6
  • Karsten Lentzsch's JGoodies me ha sido muy útil para el diseño arquitectónico, especialmente en lo que respecta al patrón del modelo de presentación, los enlaces y la validación. Consulte su articles y libraries.
  • Utilice un patrón de tipo MVC. Digo "me gusta" porque el objetivo es realmente separar la vista del modelo, no conformarme a un sabor específico de MVC. Yo prefiero usar Presentation Model.
  • MiGLayout - Lo uso para todo a menos que lo haga un administrador de diseño básico.
  • Modular y reutilizar todo lo que pueda.
  • WindowBuilder Pro para Eclipse: el mejor diseñador visual porque funciona con código existente/editado y no lo bloquea. ¡Y ahora es gratis! No tengo problemas con el uso de diseñadores, porque la vista debe estar separada del resto del código.
  • Netbeans Platform (RCP) - El único marco Swing real.Espero aprender y usar esto cuando tenga tiempo, porque parte del trabajo de un framework es abordar inquietudes como la tuya.
  • JavaBuilders - Proyecto genial que permite UI declarativas, pero no estoy seguro de que sea lo suficientemente maduro como para arriesgarlo, especialmente con un proyecto existente. Sin embargo, es interesante leer su libro en PDF solo para comprender los problemas que están tratando de resolver.
Cuestiones relacionadas