2011-12-22 13 views
8

Para ir directamente a mi pregunta.Java - Hacer proyectos de GUI a gran escala

¿Cómo se hacen proyectos de GUI a gran escala? Hasta ahora, no he hecho ningún proyecto de GUI más grande, pero en lo que estoy trabajando ahora creció bastante rápido y bastante grande y ahora estoy atrapado con una enorme pila de código que es realmente molesto y molesto.

Como vengo del campo de desarrollo web estoy acostumbrado a los frameworks MVC, así que tengo 3 paquetes en mis proyectos Modelo donde guardo clases que interactúan con archivos o db, Vistas donde guardo mis clases para formularios o GUI y controlador paquete donde guardo la mayoría de mi lógica.

Me han dicho que separe mi lógica y mantenga las acciones en una clase y los oyentes en otra clase, pero no tengo idea de cómo vincular todo eso.

Hasta ahora solo tengo 1 clase de controlador donde ejecuto todos los métodos con respecto a qué está sucediendo en la GUI una vez que se invoca.

package pft.controller; 


import java.io.IOException; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.swing.JLabel; 
import javax.swing.JComboBox; 
import javax.swing.JTree; 
import java.awt.event.*; 
import javax.swing.JProgressBar; 
import pft.view.Invoke_GUI; 
import pft.model.Events; 
import pft.model.Parse; 

public class Tower_Controller { 

    public Tower_Controller() { 
    } 
    //Global variables 
    String isSelected = null; 
    int hasModules = 0; 
    int cap = 0; 
    int cpu = 0; 
    int shield = 0; 
    int armor = 0; 

    public void setName(String name){ 
     this.isSelected = name; 
    } 

    public String getName(){ 
     return this.isSelected; 
    } 

    public void setCap(int cap){ 
     this.cap = cap; 
    } 

    public int getCap(){ 
     return this.cap; 
    } 

    public void setCpu(int cpu){ 
     this.cpu = cpu; 
    } 

    public int getCpu(){ 
     return this.cpu; 
    } 

    public void setShield(int shield){ 
     this.shield = shield; 
    } 

    public int getShield(){ 
     return this.shield; 
    } 

    public void setArmor(int armor){ 
     this.armor = armor; 
    } 

    public int getArmor(){ 
     return this.armor; 
    } 


    public void invoke() throws IOException { 
     Invoke_GUI runnable = new Invoke_GUI(); 
     final JLabel tower_name = runnable.tower_name; 
     final JComboBox tower_select = runnable.tower_select; 
     final JTree module_browser = runnable.module_browser; 
     final JTree selected_modules = runnable.selected_modules; 

     final JProgressBar cap_bar = runnable.cap_bar; 
     final JProgressBar cpu_bar = runnable.cpu_bar; 

     final JLabel em_res = runnable.em; 
     final JLabel th_res = runnable.thermic; 
     final JLabel ki_res = runnable.kinetic; 
     final JLabel ex_res = runnable.explosive; 

     setTowerName(tower_name, tower_select); 
     removeTower(tower_name); 
     runnable.setVisible(true);  

    } 

    public void removeTower(final JLabel tower_name) { 
     tower_name.addMouseListener(new MouseListener() { 

      @Override 
      public void mouseClicked(MouseEvent e) { 
       if (hasModules == 1 & isSelected != null) { 
        Events evt = new Events(); 
        evt.towerHasModules(); 
       } else if (isSelected == null) { 
       } else { 
        tower_name.setText("No Control Tower selected"); 
        isSelected = null; 
       } 
      } 

      @Override 
      public void mousePressed(MouseEvent e) { 
      } 

      @Override 
      public void mouseReleased(MouseEvent e) { 
      } 

      @Override 
      public void mouseEntered(MouseEvent e) { 
      } 

      @Override 
      public void mouseExited(MouseEvent e) { 
      } 
     }); 
    } 

    public void updateVariables(String name) throws IOException{ 
     Parse tower = new Parse(); 
     String data[] = tower.towerData(name); 
     Integer x = Integer.valueOf(data[1]).intValue(); 
     setCap(x); 
    } 

    public void setTowerName(final JLabel tower_name, final JComboBox tower_select) { 
     tower_select.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       if (isSelected != null) { 
        Events evt = new Events(); 
        evt.towerSelected(isSelected); 
       } else { 
        tower_name.setText(tower_select.getSelectedItem().toString()); 
        setName(tower_name.toString()); 
        try { 
         updateVariables(tower_name.toString()); 
        } catch (IOException ex) { 
         Logger.getLogger(Tower_Controller.class.getName()).log(Level.SEVERE, null, ex); 
        } 
       } 
      } 
     }); 
    } 


} 

Hay una gran cantidad de tutoriales y ejemplos de cómo hacer pequeñas por lo general una sola clase Java GUI pero no hay tutoriales o ejemplos sobre cómo hacer proyectos que son poco más grande que una sola clase.

Gracias de antemano por toda la ayuda y asesoramiento .

+0

eche un vistazo a la http://en.wikipedia.org/wiki/Mediator_pattern –

+0

Vea también ['MVCGame'] (http://stackoverflow.com/a/3072979/230513). – trashgod

Respuesta

6

Aquí está mi consejo para el desarrollo de Swing en general. Discute la importancia de usar Controladores para unir las necesidades de la vista y la interacción del modelo.

GUI guidelines for swing

proyecto oscilación pasado hice he diseñado un marco MVC que utiliza la primavera para definir el modelo del programa y los controladores, a continuación, utiliza anotaciones en el controlador de cable hasta eventos distribuidos por la vista en los métodos de la controlador. La vista tenía acceso al despachador de eventos que era un bus de eventos, y los eventos enviados a través del bus llamados métodos en el Controlador a través de las anotaciones. Esto permitió a cualquier Controlador responder a eventos desde la Vista. Así que cuando un Controlador se hizo demasiado grande, fue muy simple refactorizar cada conjunto de métodos en otro Controlador, y la vista o modelo no tuvo que cambiar.

La belleza del bus de eventos era que también se podía compartir con el modelo para que el modelo pudiera despachar eventos asíncronos para los que el Controlador podría registrarse también. Parecía algo así como:

public class SomeController { 

    private AuthenticationModel authenticationModel; 

    private LoginService loginService; 

    private MyApp view; 

    @Listener(event = "login") 
    public void login(LoginEvent event) { 
     view.showWaitDialog(); 
     loginService.login(event.getUserName(), event.getPassword()) 
     .onResult(new Callback<User>() { 
      public void onResult(User user) { 
       authenticationModel.setUser(user); 
       view.hideWaitDialog(); 
       view.showStartScreen(user); 
      } 
     }); 
    } 

} 

Una vez que este marco estaba en su lugar fue increíble lo rápido que podíamos hacer las cosas. Y se mantuvo bastante bien a medida que agregamos características. He hecho mi parte justa de grandes proyectos Swing (3 hasta la fecha), y esta arquitectura marcó una gran diferencia.

+0

+ 1 para el bus – Bill

+0

Su marco parece ser realmente interesante, pero ¿podría agregar más detalles sobre el modelo y la vista? (Me gustaría implementar su marco de trabajo) Tengo el mismo problema que Sterling Duchess pero no estoy familiarizado con Spring y las anotaciones Java :( – AwaX

3

La forma más fácil de escalar una GUI es hacer que todo se acople de manera poco precisa. Los eventos (Swing's y los tuyos) son la mejor manera de hacer esto. A menos que una clase esté creando o mostrando directamente un elemento GUI, no debería saber o preocuparse por nada más en la interfaz de usuario.

El controlador debe continuar haciendo lo que se supone que debe hacer: disparar eventos en respuesta a otros eventos. Sin embargo, estos eventos deben ser eventos a nivel de aplicación definidos por las necesidades de su aplicación. El controlador no debe directamente manipular los elementos de la GUI. En su lugar, debe crear componentes (tal vez solo subclases de JWhatever) que se registren con el controlador como interesados ​​en los eventos.

Por ejemplo, cree una interfaz TowerEventListener con una función nameChanged(). El controlador también tiene una función changeTowerName(), que cuando se llama, actualiza el modelo (una clase Tower) y luego llama al nameChanged() en todos los TowerEventListeners registrados.

A continuación, cree una clase de TowerRenamer que, por ejemplo, subclasifique JDialog (es decir, una ventana emergente) que incluya un cuadro de texto y un botón Aceptar junto con una referencia al Controlador. Cuando el usuario hace clic en Aceptar, se llama al Controller.changeTowerName(). Otras partes de su GUI que se registren como TowerEventListeners recibirán el evento y se actualizarán según sea necesario (tal vez actualizando un JLabel en la interfaz de usuario).

Nota, si sus necesidades son lo suficientemente simples, puede simplemente usar PropertyChangeEvents y no preocuparse por una estructura de interfaz de eventos completa. PropertyChangeSupport puede ser utilizado por el controlador para disparar notificaciones de eventos.

2

Además del gran consejo ya dado, recomendaría leer algo de lo que Trygve Reenskaug ha escrito y/o ha registrado on his MVC page. Estuvo allí durante el desarrollo de este estilo arquitectónico a finales de los 70. Su informe técnico de dos páginas titulado Models - Views - Controllers de diciembre de 1979 presenta la descripción más concisa del modelo, vista y controlador.

De particular interés, las vistas son ambos observadores y manipuladores del modelo. El controlador se ocupa principalmente de organizar (cablear) las vistas y traducir la entrada del usuario en las interacciones con el modelo. Varios de los frameworks MVC tienen el controlador retransmitiendo datos desde el modelo a la vista, esto es simplemente incorrecto. Un paper from earlier in 1979 incluía el concepto de un editor como un compuesto de vistas relacionadas. El editor fue descartado; su funcionalidad se movió tanto al controlador como a la vista.

Otro artículo que es bueno para describir cómo aplicar esta guía es Burbeck's How to use Model-View-Controller. Está escrito con Smalltalk en mente, por lo que no se puede traducir fácilmente a Java, pero es una buena descripción de cómo aplicar la guía.

Creo que lo más importante a tener en cuenta es que el estilo MVC original se creó para interfaces de usuario que incluían más de una vista (representación) del mismo modelo. Esto realmente funciona bien para las interfaces de usuario, pero no se traduce excepcionalmente bien en el mundo de los servicios web. Usar MVC para una GUI te permite ver y entender realmente el poder de este estilo.

Cuestiones relacionadas