5

我正在尝试编写一个非常简单的 Java 示例来学习 MVC。它是一个 JButton,单击时会增加一个计数器并显示到目前为止的单击次数。

我将模型、视图和控制器分解为单独的类,并认为我走在正确的道路上,但是当我单击按钮时,显示计数器的 JLabel 继续保持在 0。

有人可以快速查看一下为什么应该显示点击次数的 JLabel 始终保持为 0 吗?

谢谢

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
4

5 回答 5

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

==不适用于字符串(或对象)相等比较。equals方法是你应该使用的。

此外,我认为您对public String getActionCommand()方法感兴趣,而不是public Object getSource().

一个小测试

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();

和输出

javax.swing.JButton[,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.5,border=javax.swing.plaf.BorderUIResource$CompoundBorderUIResource@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=点击,defaultCapable=true]
点击

应该说明原因。

更新

尝试

if (arg0.getActionCommand().equals("Click"))
于 2012-10-08T16:38:43.740 回答
0

我现在明白为什么了。您创建了两个不同的模型对象。一个在控制器中,一个在 Main() 中 - 它是哪一个?

另一个建议.. 创建一个 MainController 类。这应该有你的 Main 方法。您的主要方法创建另一个控制器负责创建您的视图和模型。将此控制器用作桥接器。

于 2012-10-08T16:39:20.150 回答
0

您可以尝试在视图类上访问您的按钮:

公共 JButton getButton(){

返回 jbutton1;

}

公共无效 setButton(JButton 按钮){

this.jbutton1 = 按钮;

}

并在您的控制器类中访问您的按钮,如下所示:

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

...

}

我一直这样做,我从来没有任何错误......

于 2013-01-04T15:14:43.263 回答
0

该数字始终保持为零,因为您正在更新错误的View. 在您的Controller班级中,您创建另一个未显示的实例。

v = new View(this, m);

您可以通过添加一个 setter 来传入您的主实例:

class Controller implements ActionListener {
    Model m;
    View v;

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

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

ActionEvent.getSource()返回组件引用,但jButton1不公开可见。要解决此问题,您可以为按钮添加 getter 或使用 action 命令:

if (arg0.getActionCommand().equals("Click")) {
于 2012-10-08T17:29:04.260 回答
0

有几个问题:

  • 该视图显示的实际数据通常来自模型而不是控制器。

    因此,您在视图中的代码
    jLabel1.setText("Click Count = " + c.getClickCount());
    应更改为
    jLabel1.setText("Click Count = " + m.getClickCount());

  • 在控制器内部,您创建了模式和视图的新实例,在 main() 方法中,您再次创建了控制器和视图的新实例。所以本质上,Controller 类正在处理不同的视图和模型对象。

一般来说,但它不是一个石刻标准:

  • 视图有一个模型,它不引用控制器
  • 模型是独立的,不引用视图或控制器
  • 控制器既有视图又有模型。
于 2012-10-08T16:38:34.567 回答