【问题标题】:Where do I implement my functions?我在哪里实现我的功能?
【发布时间】:2016-12-28 00:37:07
【问题描述】:

我正在尝试与 Java Swing 一起练习我的 OOP 技能,但我目前陷入困境。我正在尝试制作一种类似于您在手机上看到的计算器 gui。我不知道我应该如何实现每个按钮按下的功能。现在我只是想在按下按钮时在屏幕上显示数字(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

【问题讨论】:

  • 按下按钮有什么作用?如果您只是构建一个稍后评估的表达式并将其显示给用户,那么处理[0-9x/-+] 按钮将是相同的,将按钮的符号附加到表达式并更新显示的字符串。其余的按钮显然有不同的用途,需要自定义动作监听器。
  • 另见calculator example。它使用ScriptEngine 来评估文本字段中的表达式。

标签: java swing oop calculator


【解决方案1】:

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


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

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

  1. 你是用户——你与视图交互。控制器采取你的行动并解释它们。如果您点击一个按钮,控制器的工作就是确定其含义以及应如何根据该操作操作模型。
  2. 控制器要求模型改变其状态。 当控制器从视图接收到一个动作时,它可能需要告诉视图改变作为结果。例如,控制器可以启用或禁用界面中的某些按钮或菜单项。
  3. 模型在其状态发生更改时通知视图。 当模型中的某些内容发生更改时,基于您执行的某些操作(例如单击按钮)或其他一些内部更改(例如播放列表已开始),模型会通知视图其状态已更改。
  4. 控制器也可能要求改变视图。
  5. 视图向模型询问其状态。视图直接从模型中获取其显示的状态。例如,当模型通知视图开始播放新歌曲时,视图会从模型请求歌曲名称并显示它。由于控制器请求对视图进行一些更改,视图也可能会向模型询问状态。

可以在上面的链接on Oracle's website 中找到对MVC 模式的更详细和深入的解释,并通过简单的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);
        }

    }

}

代码注释:

  • 查看 arraysfor loop 以帮助您简化按钮的声明。
  • 在添加所有组件以适应 JFrame 的子级大小后,不要设置 JFrames 大小,而是在 JFrame 上调用 pack()
  • 不要扩展JFrame,而是创建一个实例并进行必要的修改。
  • EDT(事件调度线程)上运行您的代码以避免在您的 GUI 中“冻结”。欲了解更多信息,请查看The Java™ Tutorials - Concurrency in Swing
  • 下次发帖时请考虑发帖,为了尽快获得更好的帮助,请发帖MCVE

【讨论】:

    【解决方案2】:

    您应该在“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);`
        }
    

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

    【讨论】:

    • 为什么要将动作监听器的逻辑代码放在单独的方法中?
    猜你喜欢
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    • 1970-01-01
    • 2020-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-26
    相关资源
    最近更新 更多