【问题标题】:Refresh GUI Objects in a Java Application刷新 Java 应用程序中的 GUI 对象
【发布时间】:2020-03-24 22:39:03
【问题描述】:

第一次发帖。我觉得这应该是相当直截了当的,但是在搜索和尝试之后,我一直没有解决方案。我在一个非常简单的 MVC 程序中重新创建了我的问题——它在这个示例应用程序和我的实际应用程序中表现相同;我显然在这两个地方都犯了同样的错误。

在我的 Java 桌面应用程序中,我在“视图”类中有 GUI 代码。此类严格负责 GUI 的外观,确保所有可视对象都布置在屏幕/窗口上。 “控制器”处理所有程序流程,并负责监听用户事件,例如按钮单击,然后调用必要的 View 方法从/向 GUI 检索或放入数据。

下面的类以一种非常简单的方式执行此操作 - 它所做的只是绘制一个小的 JFrame 窗口,其中包含一个带有 4 个对象、3 个 JButton 和一个 JTextField 的 JPanel。当按下 3 个按钮中的任何一个时,该按钮的编号 1、2 或 3 将显示在文本字段中。只是,该字段没有更新。我在视图中有一个方法,它调用 JFrame 的 repaint() 和 revalidate() 方法,在按下按钮后更新文本字段后立即从控制器调用。我有一个打印语句将文本写入控制台,所以我知道这部分有效。我也相信文本字段的更新是有效的,因为我有一个消息对话框显示它的值。我的理解是 JFrame.repaint();应该重新绘制框架及其所有后代(其中的对象),它只是,不是。

提前感谢您的帮助。这是我的示例代码:

Model.java(当前为空)

package com.techbybryan;

public class Model {
}

View.java

package com.techbybryan;

import javax.swing.*;
import java.awt.*;

public class View {

    JButton button1 = new JButton( "One" );
    JButton button2 = new JButton( "Two" );
    JButton button3 = new JButton( "Three" );
    JTextField jTextField = new JTextField();
    JPanel jPanel = new JPanel();
    JFrame jFrame = new JFrame( "Gui Test" );

    public View(){

        jPanel.add( button1 );
        jPanel.add( button2 );
        jPanel.add( button3 );
        jPanel.add( jTextField );
        jFrame.add( jPanel );

        jFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        jFrame.setSize(new Dimension( 500, 100 ) );
        jFrame.setLocationRelativeTo( null );
        jFrame.setResizable( false );
        jFrame.setVisible( true );
    }

    public JButton getButton1() {
        return button1;
    }

    public void setButton1( JButton button1 ) {
        this.button1 = button1;
    }

    public JButton getButton2() {
        return button2;
    }

    public void setButton2( JButton button2 ) {
        this.button2 = button2;
    }

    public JButton getButton3() {
        return button3;
    }

    public void setButton3( JButton button3 ) {
        this.button3 = button3;
    }

    public JTextField getjTextField() {
        return jTextField;
    }

    public void setJTextField( JTextField jTextField ) {
        this.jTextField = jTextField;
    }

    public void repaint(){
        jFrame.revalidate();
        jFrame.repaint();
        JOptionPane.showMessageDialog( null, jTextField );
    }
}

Controller.java

package com.techbybryan;

import javax.swing.*;

public class Controller {
    Model      model;
    View       view;
    Controller controller;

    public Controller( Model model, View view ){
        this.model = model;
        this.view = view;
    }

    public void init(){
        view.getButton1().addActionListener( e -> setOutputText( "One" ) );
        view.getButton2().addActionListener( e -> setOutputText( "Two" ) );
        view.getButton3().addActionListener( e -> setOutputText( "Three" ) );
    }

    public void setOutputText( String textToDisplay ){
        System.out.println( textToDisplay );

        view.setJTextField( new JTextField( textToDisplay ) );
        view.repaint();
    }
}

GuiText.java

package com.techbybryan;

public class GuiTest {

    public static void main(String[] args) {
        Model      model      = new Model();
        View       view       = new View();
        Controller controller = new Controller( model, view );

        controller.init(  );
    }
}

非常感谢您提出的任何建设性建议;感谢您的反馈。

【问题讨论】:

    标签: java swing model-view-controller


    【解决方案1】:

    您的控制器中的这段代码不正确:

    view.setJTextField( new JTextField( textToDisplay ) );
    

    控制器不应该将组件添加到视图中,而应该是该方法,即 actionlistener,应该更改模型的状态,这是您无法做到的,因为您的模型类莫名其妙地为空。

    简而言之,你是在倒退——你应该让你的模型首先工作,然后连接控件和视图以首先使用模型最重要的是。您的模型应该在视图发生更改时通知视图(PropertyChangeListener 在这里可以很好地工作),然后视图应该更新当前显示的 JTextField 中的显示(添加新的 JTextField ——对不起,直言不讳,但那太疯狂了),基于模型的状态。

    此外,请摆脱所有这些重绘和重新验证,因为这些代码不会帮助您解决基本问题,而且是不必要的。

    还要注意,我会去掉这段代码:

    public void setJTextField( JTextField jTextField ) {
        this.jTextField = jTextField;
    }
    

    不如做一些类似的事情:

    public void setJTextFieldText(String text) {
        this.jTextField.setText(text);
    }
    

    不要不必要地添加组件,而是更改您已经拥有的组件的状态

    【讨论】:

    • 谢谢! setText(text) 正是所需要的。我没有对可用的方法进行足够的研究,而是过于依赖 IntelliJ 为该字段生成的 setter。在那里学到了一些教训。我成功地将这一点带到了这个问题出现的“真实”应用程序中。您还给了我很多关于代码所属位置的思考,以及在此示例程序中模型应该做什么而不是。我会花一些时间思考和试验。再次感谢。
    猜你喜欢
    • 2013-02-14
    • 1970-01-01
    • 2015-11-17
    • 2012-05-15
    • 1970-01-01
    • 2020-11-03
    • 2023-04-02
    • 2011-11-05
    • 2011-12-25
    相关资源
    最近更新 更多