Java Swing 在等待方法时在 actionPerformed 函数中更改 UI 两次

Posted

技术标签:

【中文标题】Java Swing 在等待方法时在 actionPerformed 函数中更改 UI 两次【英文标题】:Java Swing change UI twice in the actionPerformed function while waiting for a method 【发布时间】:2021-05-27 05:11:59 【问题描述】:

简单的问题解释:当在我的 UI 中按下按钮时,它会调用不同的类来运行一些逻辑。按照设计,这个逻辑大约需要一分钟。我想在调用函数说“请稍候等等”之前更新 JTextField,然后在函数完成后更新该文本。我看到的是 UI 在退出 actionPerformed 函数之前不会刷新,所以在文本更新为“完成”之前什么都不会发生

示例如下:

JTextField warn = new JTextField("Press submit to begin");//This is a member var
public void actionPerformed(ActionEvent ev) 
        Object source = ev.getSource();

        if(source == submitButton) 
            warn.setText("Please wait 60 seconds");
            Display.doThingThatTakesAMinute();
            warn.setText("Complete");
        
    

根据上面的描述,当按钮被按下时,它会保持按下状态 60 秒,显示原来的“按下提交开始”,直到它显示“完成”。有什么帮助吗?

【问题讨论】:

【参考方案1】:

使用SwingWorker 在EDT 之外运行较长的进程。 使用SwingWorker可以防止 GUI 冻结,并允许您显示长期过程的中间结果和最终结果:

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

public class SwingWorkerWaitDemo 

    public static void creategui()

        JFrame f = new JFrame("SwingWorker Demo");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLocationRelativeTo(null);
        f.add(new MainPanel());
        f.pack();
        f.setVisible(true);
    

    public static void main(String[] args) 
        creategui();
    


class MainPanel extends JPanel 

    private MyWorker swingWorker;
    private final JLabel interimResults;
    private final JButton submit, cancel;
    private final JTextField warn;

    MainPanel() 
        setLayout(new BorderLayout(2, 2));
        submit = new JButton("Submit");
        submit.addActionListener(e->start());
        cancel = new JButton("Stop");
        cancel.setEnabled(false);
        cancel.addActionListener(e->cancel());
        JPanel ssPane = new JPanel(new FlowLayout(FlowLayout.CENTER));
        ssPane.add(submit); ssPane.add(cancel);
        add(ssPane, BorderLayout.PAGE_START);

        interimResults = new JLabel();
        JPanel outputPane = new JPanel(new FlowLayout(FlowLayout.CENTER));
        outputPane.add(interimResults);
        add(outputPane, BorderLayout.CENTER);

         warn = new JTextField("Press Submit to begin");
        JPanel responsePane = new JPanel();
        responsePane.add(warn);
        add(responsePane, BorderLayout.PAGE_END);
    

    @Override
    public Dimension getPreferredSize()
        return new Dimension(400, 100);
    

    private void start() 
        submit.setEnabled(false);
        cancel.setEnabled(true);
        swingWorker = new MyWorker();
        swingWorker.execute();
        warn.setText("Long process is running. Press Cancel to stop.");
    

    private void cancel() 
        cancel.setEnabled(false);
        swingWorker.setStop(true);
    

    class MyWorker extends SwingWorker<Integer, Integer> 

        private boolean stop = false;

        @Override
        //long processing done in background
        protected Integer doInBackground() throws Exception 

            int counter = 0;

            while(! stop && counter < 60)
                publish(counter++);
                Thread.sleep(1000);
            
            return counter;
        

        @Override
        //show interim results
        protected void process(List<Integer> chunks) 
            for (int i : chunks) 
                interimResults.setText(String.valueOf(i));
            
        

        @Override
        //invoked when swingworker has finished
        protected void done() 
            warn.setText(stop ? "Process stopped": "All done");
            cancel.setEnabled(false);
        

        void setStop(boolean stop) 
            this.stop = stop;
        
    

【讨论】:

以上是关于Java Swing 在等待方法时在 actionPerformed 函数中更改 UI 两次的主要内容,如果未能解决你的问题,请参考以下文章

java - 如何在Java Swing中的while循环迭代后等待

Java Swing:提交多个变量的Action Event

200分 Java Swing 刷新问题

java swing 中的列表框JList如何在程序中动态的添加和删除元素

java swing中Timer类的学习

Java在Swing中如何实现弹出一个对话框的效果?