2012-10-08 76 views
5

Estoy tratando de escribir un ejemplo de Java realmente simple para aprender MVC. Es un JButton que al hacer clic aumenta un contador y muestra la cantidad de clics hasta ahora.Java Click Counter usando MVC

estalló el Modelo, Vista y Controlador en clases separadas, y pensé que estaba en el camino correcto, pero cuando hago clic en el botón de la JLabel que muestra el contador continúa a permanecer en 0.

Puede alguien Eche un vistazo rápido y vea por qué el JLabel que debe mostrar el número de clics siempre permanece en 0?

Gracias

View 

package mvc; 
import javax.swing.JButton; 
import javax.swing.JLabel; 
import javax.swing.JTextArea; 
import javax.swing.SwingUtilities; 
import javax.swing.WindowConstants; 


public class View extends javax.swing.JFrame { 
    private JButton jButton1; 
    private JLabel jLabel1; 
    private Controller c; 
    private Model m; 

    /** 
    * Auto-generated main method to display this JFrame 
    */ 
    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       Controller c = new Controller();  

       Model m = new Model(); 

       View inst = new View(c,m); 
       inst.setLocationRelativeTo(null); 
       inst.setVisible(true); 
      } 
     }); 
    } 

    public View(Controller c, Model m) { 
     super(); 
     this.c = c;  
     this.m = m; 
     initGUI(); 
    } 

    private void initGUI() { 
     try { 
      setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 
      getContentPane().setLayout(null); 
      { 
       jButton1 = new JButton(); 
       getContentPane().add(jButton1, "Center"); 
       jButton1.setText("Click"); 
       jButton1.setBounds(314, 180, 101, 34); 
       jButton1.addActionListener(c); 
      } 
      { 
       jLabel1 = new JLabel(); 
       getContentPane().add(getJLabel1()); 
       jLabel1.setText("Click Count = " + c.getClickCount()); 
       jLabel1.setBounds(439, 183, 91, 27); 

      } 
      pack(); 
      this.setSize(818, 414); 
     } catch (Exception e) { 
      //add your error handling code here 
      e.printStackTrace(); 
     } 
    } 

    public JLabel getJLabel1() { 
     return jLabel1; 
    } 
} 

End View 

Controller class 

package mvc; 

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

public class Controller implements ActionListener 
{ 
    Model m; 
    View v; 

    public Controller() 
    { 
     m = new Model();   
     v = new View(this, m); 
    } 

    @Override 
    public void actionPerformed(ActionEvent arg0) 
    { 
     if (arg0.getSource() == "Click") 
     { 
      m.addClick(); 
      v.getJLabel1().setText("Click count = " + getClickCount()); 
     } 

    } 

    public int getClickCount() 
    { 
     return m.getClicks(); 
    } 
} 

End Controller class 

Model class 

package mvc; 

public class Model 
{ 
    private int clicks; 

    public Model() 
    { 
     clicks = 0; 
    } 

    public void addClick() 
    { 
     clicks++; 
    } 

    public int getClicks() 
    { 
     return clicks; 
    } 
} 

End Model class 

Respuesta

0

Hay par de problemas:

  • Los datos reales Si eso vista muestra viene generalmente desde el modelo no desde el controlador.

    Así que su código en la vista
    jLabel1.setText("Click Count = " + c.getClickCount());
    debería cambiar a
    jLabel1.setText("Click Count = " + m.getClickCount());

  • dentro del controlador, se crea una nueva instancia de la modalidad y la vista y dentro del método main() de nuevo crear una nueva instancia de controlador y vista. Entonces, esencialmente, la clase Controller está trabajando en una vista y objetos de modelo diferentes.

En general, pero no es un estándar de la piedra-entalladuras:

  • la vista tiene un modelo, doesent referirse al controlador
  • El modelo es independiente y doesent se refiere a ver o controlador
  • El controlador tiene vista y modelo.
+0

Hola, r eliminó el modelo del método main() y el constructor View ahora solo toma un controlador como parámetro. – user1729409

+0

Normalmente, la vista toma un modelo. El modelo no toma nada. El controlador toma tanto el modelo como la vista. Entonces el Modelo no sabe acerca de la Vista y el Controlador. La vista solo conoce y usa el modelo, no el controlador. El controlador puede referirse tanto al modelo como a la vista –

0
if (arg0.getSource() == "Click") 

== no es para la cadena (u objeto) comparación de igualdad. equals método es lo que debe usar en su lugar.

Por otra parte, creo que está interesado en el método public String getActionCommand() en lugar de public Object getSource().

Una pequeña prueba

JButton btn = new JButton(); 
btn.setText("Click");  
btn.addActionListener(new ActionListener() { 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     System.out.println(e.getSource()); 
     System.out.println(e.getActionCommand()); 
    } 
}); 
btn.doClick(); 

y la salida

 
javax.swing.JButton[,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.5,bo[email protected]1f5b0afd,flags=296,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,disabledSelectedIcon=,margin=javax.swing.plaf.InsetsUIResource[top=2,left=14,bottom=2,right=14],paintBorder=true,paintFocus=true,pressedIcon=,rolloverEnabled=true,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=Click,defaultCapable=true] 
Click 

deben ilustrar por qué.

actualización

Try

if (arg0.getActionCommand().equals("Click")) 
+0

Hola, no estoy seguro de cómo actualizar mi código, pero eliminé la parte "if (arg0.getSource() ==" Click ")" ya que solo tengo 1 botón. Todavía no parece actualizar mi contador de clics. – user1729409

+0

@ user1729409: actualicé mi respuesta. ¿Puedes intentarlo? –

+0

Hola, lo probé y todavía no funciona. – user1729409

0

veo por qué ahora. Tienes dos objetos modelo diferentes creados. Uno en el controlador y otro en Main() - ¿Cuál es?

Otro consejo ... crear una clase MainController. Esto debería tener su método Principal. Su método principal crea otro Controlador responsable de crear su Vista y Modelo. Utilice este controlador como puente.

+0

Así que terminé haciendo que esto funcione. Ahora tengo la Vista con variables de instancia para el Modelo y el Controlador. El controlador toma un modelo y una vista como argumentos para su constructor. El Modelo no sabe nada sobre el Controlador o la Vista. Creé una clase MainController para crear y ejecutar la clase View. ¡Muchas gracias a todos los que ayudaron! – user1729409

0

El número siempre se mantiene en cero porque está actualizando la instancia incorrecta de View. En su clase Controller, crea otra instancia que no se muestra.

v = new View(this, m); 

Usted podría pasar en su lugar en la instancia principal mediante la adición de un regulador:

class Controller implements ActionListener { 
    Model m; 
    View v; 

    public Controller() { 
     m = new Model(); 
    } 

    public void setView(View v) { 
     this.v = v; 
    } 
    ... 

ActionEvent.getSource() devuelve una referencia de componente, pero jButton1 no es visible para el público. Para solucionar puede agregar un captador para el botón o utilice el comando de acción:

if (arg0.getActionCommand().equals("Click")) { 
0

que tal vez podría intentar hacer de acceso a su botón en la clase de vista:

pública JButton getButton() {

return jbutton1;

}

pública botón SET vacío (botón JButton) {

this.jbutton1 = botón;

}

y en su controladora de Acceso a la clase a su botón de la siguiente manera:

si (arg0.getSource() == v.getButton()) {

...

}

siempre lo hice así y nunca tuve ningún error ...