我希望GUI在对象实例化并实际完成工作之前将按钮的标题从"Go"更改为"Working…"。完成后,我希望按钮的标题切换回"Go"。"
代码如下:
private class convert implements ActionListener {
public void actionPerformed(ActionEvent e) {
JButton button = (JButton)e.getSource();
button.setText("Working...");
button.setEnabled(false);
anObject name = new AnObject();
boolean result = name.methodName(chooser.getSelectedFile(),encoding);
// A bunch of stuff was here but irrelevant to the question,
// so it was removed to save room.
button.setEnabled(true);
button.setText("Go");
}
实际发生的是name被实例化,methodName被调用,然后按钮在屏幕上得到更新,尽管我已经告诉VM先改变按钮标题。
我的工作理论是,鉴于我没有使这个程序线程化,这与操作优先级或JVM的内部线程或其他东西有关…
有什么建议吗?
我知道您已经接受了一个解决方案,但是由于您遇到了"gui冻结"综合症,您肯定遇到了线程问题,而invokeLater无法解决您的问题。正如前面提到的,你需要一个SwingWorker或者一些后台线程来解决这个问题。另外,我认为这是一个使用AbstractAction而不是ActionListener的好例子。例如:
import java.awt.Dimension;
import java.awt.event.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class Convert extends AbstractAction {
private static final long SLEEP_TIME = 3000; // 3 seconds
private String enabledText;
private String disabledText;
public Convert(String enabledText, String disabledText) {
super(enabledText);
this.enabledText = enabledText;
this.disabledText = disabledText;
}
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (!(source instanceof JButton)) {
return;
}
final JButton button = (JButton) source;
setButtonEnabled(button, false);
new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
// TODO: long-running code goes here.
// Emulated by Thread.sleep(...)
Thread.sleep(SLEEP_TIME);
return null;
}
@Override
protected void done() {
setButtonEnabled(button, true);
}
}.execute();
}
public void setButtonEnabled(JButton button, boolean enabled) {
if (enabled) {
button.setText(enabledText);
button.setEnabled(true);
} else {
button.setText(disabledText);
button.setEnabled(false);
}
}
private static void createAndShowUI() {
JFrame frame = new JFrame("Convert");
frame.getContentPane().add(new ConvertGui());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
@SuppressWarnings("serial")
class ConvertGui extends JPanel {
public ConvertGui() {
add(new JButton(new Convert("GO", "Working...")));
}
@Override
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
}
一个"ActionPerformed"回调发生在事件线程中,通常在它返回之前GUI上不会更新任何内容。如果您想更新gui,做一些事情,然后再次更新它,您将需要更新gui并生成一个线程并返回。然后线程必须执行它的动作,然后执行swingutility。
试试swinguutilities . invokelater ().
private class convert implements ActionListener {
public void actionPerformed(ActionEvent e) {
final JButton button = (JButton)e.getSource();
button.setText("Working...");
button.setEnabled(false);
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
anObject name = new AnObject();
boolean result = name.methodName(chooser.getSelectedFile(),encoding);
// A bunch of stuff was here but irrelevant to the question,
// so it was removed to save room.
button.setEnabled(true);
button.setText("Convert");
}
});
}