我在哪里实现我的功能?

Where do I implement my functions?

我正在尝试练习我的 OOP 技能以及 Java Swing,但我目前被卡住了。我正在尝试制作一个类似于您在 phone 上看到的那种计算器图形用户界面。我不知道我应该如何实现每个按钮按下的功能。现在我只是想在按下按钮时在屏幕上显示数字(JLabel 对象)。我还附上了一张我目前拥有的 GUI 图片。

我应该在单独的 .java 文件中实现这些功能吗?还是应该在 Calculator.java 或 Keyboard.java 文件中实施?

还有它们是如何实现的,因为如果我的按钮对象在 Keyboard.java 文件中,我不知道如何在 Calculator.java 文件中的 JLabel 对象上显示。

Calculator.java

package calculator;

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

import javax.swing.*;

public class Calculator extends JFrame
{
    public static void main(String[] args)
    {
        new Calculator();
    }

    public Calculator() //Calculator constructor??
    {
        setLayout(new GridLayout(2,1));
        this.setSize(400,600);
        this.setLocationRelativeTo(null); //center the window
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JLabel display = new JLabel();
        this.add(display);

        Keyboard kb = new Keyboard();
        this.add(kb);

        this.setVisible(true);
    }

}

Keyboard.java

package calculator;
import javax.swing.JPanel;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;

public class Keyboard extends JPanel implements ActionListener
{
    public Keyboard()
    {
        setLayout(new GridLayout(4,4));

        JButton one = new JButton("1");
        this.add(one);
        JButton two = new JButton("2");
        this.add(two);
        JButton three = new JButton("3");
        this.add(three);
        JButton plus = new JButton("+");
        this.add(plus);
        JButton four = new JButton("4");
        this.add(four);
        JButton five = new JButton("5");
        this.add(five);
        JButton six = new JButton("6");
        this.add(six);
        JButton minus = new JButton("-");
        this.add(minus);
        JButton seven = new JButton("7");
        this.add(seven);
        JButton eight = new JButton("8");
        this.add(eight);
        JButton nine = new JButton("9");
        this.add(nine);
        JButton times = new JButton("x");
        this.add(times);
        JButton zero = new JButton("0");
        this.add(zero);
        JButton clear = new JButton("clear");
        this.add(clear);
        JButton equals = new JButton("=");
        this.add(equals);
        JButton divide = new JButton("/");
        this.add(divide);
    }

    public void actionPerformed(ActionEvent e) {

    }
}

enter image description here

您应该在 'Keyboard.java' 文件本身中编写 actionPerformed() 方法

Keyboard.java

one.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            jButton1ActionPerformed(evt);
        }
    });
    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
    {
        displaystring = displaystring + "1";
        display.setText (displaystring);`
    }

您必须通过键盘 class 的构造函数传递显示的引用并将其分配给该 class 的某个实例变量,以便您可以更新键盘 class 中的显示标签太!!

使用 MVC 模式并将进入 actionPerformed(...) 方法的逻辑代码(或与此相关的任何逻辑代码)放入控制器中的相应方法 class .


MVC 模式由三个 class 组成,即 ModelViewControl,它们共同构成一个 GUI。

MVC 模式的简要总结,最初取自 this answer,但稍作修改:

  1. You’re the user — you interact with the view. The controller takes your actions and interprets them. If you click on a button, it’s the controller’s job to figure out what that means and how the model should be manipulated based on that action.
  2. The controller asks the model to change its state. When the controller receives an action from the view, it may need to tell the view to change as a result. For example, the controller could enable or disable certain buttons or menu items in the interface.
  3. The model notifies the view when its state has changed. When something changes in the model, based either on some action you took (like clicking a button) or some other internal change (like the next song in the playlist has started), the model notifies the view that its state has changed.
  4. The controller may also ask the view to change.
  5. The view asks the model for its state. The view gets the state it displays directly from the model. For instance, when the model notifies the view that a new song has started playing, the view requests the song name from the model and displays it. The view might also ask the model for state as the result of the controller requesting some change in the view.

关于 MVC 模式的更详细和深入的解释可以在上面的 link 和 on Oracle's website 中找到,并通过简单的 Google 搜索。


我选择使用 the observer pattern 进行模型-视图交互。

使用MVC结构的程序示例:

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

class Test {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                final Model model = new Model();
                final Control control = new Control(model);
                final View view = new View(model, control);

                final JFrame frame = new JFrame("MVC Example");
                frame.getContentPane().add(view);
                frame.pack();
                frame.setLocationByPlatform(true);
                frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
                frame.setVisible(true);
            }

        });
    }

    static class Model extends Observable {

        private int number;

        void setNumber(int newValue) {
            number = newValue;
            setChanged();
            notifyObservers(number);
        }

        int getNumber() {
            return number;
        }

    }

    static class View extends JPanel {

        View(Model model, Control control) {
            final JLabel label = new JLabel(Integer.toString(model.getNumber()));
            final JButton button = new JButton("Click me!");
            button.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    control.buttonPressed();
                }

            });

            setLayout(new BorderLayout());
            add(label);
            add(button, BorderLayout.SOUTH);

            model.addObserver(new Observer() {

                @Override
                public void update(Observable o, Object arg) {
                    label.setText(Integer.toString((int) arg));
                }

            });
        }

    }

    static class Control {

        private Model model;

        Control(Model model) {
            this.model = model;
        }

        void buttonPressed() {
            model.setNumber(model.getNumber() + 1);
        }

    }

}

代码注释:

  • 查看 arrays and the for loop 以帮助您简化按钮的声明。
  • 不要设置 JFrame 的大小,而是在添加所有组件以使 JFrame 适合其子项的大小后,在 JFrame 上调用 pack()
  • 不要扩展 JFrame,而是创建一个实例并进行必要的修改。
  • 运行 您在 EDT(事件调度线程)上的代码以避免在您的 GUI 中出现 "freezing"。有关详细信息,请查看 The Java™ Tutorials - Concurrency in Swing
  • 下次您 post 考虑 posting,为了尽快获得更好的帮助,post MCVE