java - Java Swing 在等待方法时在 actionPerformed 函数中更改 UI 两次
问题描述
简单的问题解释:当在我的 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 秒,显示原始的“Press submit to begin”,直到它显示“Complete”。有什么帮助吗?
解决方案
使用 a在EDTSwingWorker
之外运行一个很长的进程。
使用 a可以防止 GUI 冻结,并允许您显示长期过程的中间结果和最终结果:SwingWorker
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;
}
}
}
推荐阅读
- sql-server - 更新未添加正确的值
- for-loop - 中断 for 循环并在发生特定条件时抛出异常
- google-cloud-platform - 如何通过 Cloud Build 访问 GSM Secret 并传递给 Cloud Function
- javascript - 如何使用父对象中的 ID 引用将主对象与子对象合并到每个子对象
- windows - MidiInProc 回调在哪个上下文中执行?
- debugging - DX12 - D3D12GetDebugInterface - 应用程序请求的接口取决于 SDK 组件丢失或不匹配
- flutter - Flutter ffi无法执行功能
- r - 通过分组变量重新排序geom_col(错误:无法修改列,因为它是分组变量)
- optimization - 加载和转置八个 8 元素浮点向量
- c++ - SFML 冲突从未在我的系统中注册