smf*_*ftr 0 java concurrency swing awt actionlistener
这是我的代码:
public MyClass() {
JButton btnNext;
private void initComponents() {
btnNext = new javax.swing.JButton();
btnNext.setText("Lanjut");
btnNext.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnNextActionPerformed(evt);
}
});
}
private void btnNextActionPerformed(java.awt.event.ActionEvent evt) {
btnNext.setText("Loading...");
callingFunction();
}
}
Run Code Online (Sandbox Code Playgroud)
注意:callingFunction()是一个需要很长时间才能执行的函数.
我的问题是我的按钮文本只有在调用函数()完成后才会更改为"正在加载...".
如何立即将btnNext文本更改为"正在加载..."?
在控件返回Swing事件队列之前,不会重新绘制该按钮.在事件派发线程上调用该函数会阻塞事件队列.
作为一种解决方法,告诉它稍后运行该功能(只要它重绘完了东西):
在Java 8+中:
EventQueue.invokeLater(() -> callingFunction());
Run Code Online (Sandbox Code Playgroud)
在旧的Java中:
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
callingFunction();
}
});
Run Code Online (Sandbox Code Playgroud)
请注意,这仍然会产生在该函数运行时阻止与GUI进一步交互的副作用.如果要在后台线程中运行长任务以保持GUI交互,请使用SwingWorker.一个最小的例子,假设callingFunction返回一些String你想要用来更新显示的类型(或其他)的结果:
new SwingWorker<String,Void>() {
@Override
protected String doInBackground() throws Exception {
// called on a background thread
return callingFunction();
}
@Override
protected void done() {
// called on the event dispatch thread after the work is done
String result;
try {
result = get();
} catch (Exception e) {
throw new RuntimeException(e);
}
// do something with the result ...
someTextField.setText(result);
}
}.execute();
Run Code Online (Sandbox Code Playgroud)