Java 更新GUI以响应模型更改
我正在做我的第一个包含GUI的Java项目。我知道程序的逻辑应该与程序的视图(GUI)分开。我的问题是,我不明白在游戏逻辑发生变化后如何更新GUI,而不进行两次编码,一次在GUI中,一次在逻辑中 下面是一个非常简单的示例,说明我正在尝试做什么: 用于逻辑的类:Java 更新GUI以响应模型更改,java,swing,user-interface,model-view-controller,observers,Java,Swing,User Interface,Model View Controller,Observers,我正在做我的第一个包含GUI的Java项目。我知道程序的逻辑应该与程序的视图(GUI)分开。我的问题是,我不明白在游戏逻辑发生变化后如何更新GUI,而不进行两次编码,一次在GUI中,一次在逻辑中 下面是一个非常简单的示例,说明我正在尝试做什么: 用于逻辑的类: public class Logic { private int importantVariable; public Logic(int importantVariable){ this.importa
public class Logic {
private int importantVariable;
public Logic(int importantVariable){
this.importantVariable = importantVariable;
}
public int getImportantVariable() {
return importantVariable;
}
public void increaseImportantVariable() {
this.importantVariable++;
}
}
用于GUI的类
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GUI extends JFrame {
private Logic logic;
public GUI(Logic logic){
this.logic = logic;
this.setTitle("GUI");
this.setSize(1200, 800);
this.setLocationRelativeTo(null);//set the location to the middle of the display
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel guiPanel = new JPanel();
//create label
JLabel showVariableLabel = new JLabel(String.valueOf(logic.getImportantVariable()));
guiPanel.add(showVariableLabel);
//create Button
JButton button = new JButton();
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
logic.increaseImportantVariable();
}
});
guiPanel.add(button);
this.add(guiPanel);
}
}
主要类别:
public class Main{
public static void main(String[] args){
Logic logic = new Logic(0);
GUI gui = new GUI(logic);
gui.setVisible(true);
}
}
在本例中,GUI有一个按钮和一个显示数字的标签。如果按下该按钮,则该数字将增加。但是如何让标签显示增加的数量?
我认为更改ActionListener来更新JLabel和逻辑是不好的,因为程序已经知道了它必须知道的一切:逻辑如何工作以及逻辑如何显示。这意味着我的感觉是将ActionListener实现为
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
logic.increaseImportantVariable();
showVariableLabel.setText(String.valueOf(logic.getImportantVariable()));
}
});
这不是最好的方法,即使它有效(我错了吗?)。我认为这是因为一个真正的项目要复杂得多,而且逻辑中可能会有许多变量发生变化,这使得更新整个GUI变得更容易,而不仅仅是更新了组件
因此,我想要的是要么只更改逻辑并不断更新整个GUI(它知道如何显示整个逻辑),要么在逻辑中发生更改时调用GUI.update()之类的函数来更新整个GUI。但对于这两种方式,我都不知道如何做到这一点。我希望我的问题是可以理解的,我在思考如何以最佳方式分离逻辑和GUI时没有太大的错误。要收听模型更改,请引入侦听器界面:
interface ModelObserver {
void modelChanged();
}
修改逻辑
,以便它可以接受侦听器并使用它:
class Logic {
ModelObserver observer;
private int importantVariable;
public Logic(int importantVariable, ModelObserver observer){
this.importantVariable = importantVariable;
this.observer = observer;
}
public int getImportantVariable() {
return importantVariable;
}
public void increaseImportantVariable() {
importantVariable++;
observer.modelChanged();
}
}
Main
类充当控制器,让它将观察者添加到Model
并响应模型更改:
public class Main implements ModelObserver{
private final GUI gui;
Main(){
Logic logic = new Logic(0, this);
gui = new GUI(logic);
gui.setVisible(true);
}
@Override
public void modelChanged() {
gui.refresh();
}
public static void main(String[] args){
new Main();
}
}
将所有代码放在一起(例如,可以将整个代码复制粘贴到Main.java
并运行):
这是一个棘手的问题,但我认为程序员的回答解释了你需要知道的一切。Swing已经是一个MVC应用程序,因此试图将视图和逻辑分开是很困难的。你几乎已经做到了。动作侦听器更新模型并通知视图进行更新。视图从模型中获取信息,但从不更改模型中的任何内容。只有控制器(操作侦听器)修改模型。
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public class Main implements ModelObserver{
private final GUI gui;
Main(){
Logic logic = new Logic(0, this);
gui = new GUI(logic);
gui.setVisible(true);
}
@Override
public void modelChanged() {
gui.refresh();
}
public static void main(String[] args){
new Main();
}
}
interface ModelObserver {
void modelChanged();
}
class GUI extends JFrame {
private final Logic logic;
private final JLabel showVariableLabel;
public GUI(Logic logic){
this.logic = logic;
this.setTitle("GUI");
this.setLocationRelativeTo(null);//set the location to the middle of the display
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel guiPanel = new JPanel();
//create label
showVariableLabel = new JLabel(String.valueOf(logic.getImportantVariable()));
guiPanel.add(showVariableLabel);
//create Button
JButton button = new JButton("Increment");
button.addActionListener(e -> logic.increaseImportantVariable());
guiPanel.add(button);
this.add(guiPanel);
pack();
}
public void refresh() {
showVariableLabel.setText(String.valueOf(logic.getImportantVariable()));
}
}
class Logic {
ModelObserver observer;
private int importantVariable;
public Logic(int importantVariable, ModelObserver observer){
this.importantVariable = importantVariable;
this.observer = observer;
}
public int getImportantVariable() {
return importantVariable;
}
public void increaseImportantVariable() {
importantVariable++;
observer.modelChanged();
}
}