问题
我在 swing 中创建了一个对话框(JRE 6 update 10,Ubuntu linux)。当用户完成使用对话框时,它会被隐藏。当用户单击另一个框架中的按钮时,框上的标签会根据按钮而改变,然后框再次显示。
我遇到的问题是该框显示在标签更改之前,即使以编程方式,我以相反的顺序进行调用。这会导致该框出现,然后是标签更改,这在我们的慢速目标硬件上看起来“有问题”。EDT 似乎在标签setText(....)之前安排了框架setVisible(true ) ;它优先考虑这个呼叫。有没有办法让 EDT 安排setVisible(true)在setText(....)之后执行?
请注意,代码是从已在 EDT 上执行的按钮单击调用的,因此无法使用SwingUtilities.invokeAndWait。我试过使用invokeLater方法,但 EDT 仍然重新安排它。
重现
在调试模式下在 IDE 中运行以下代码,并在显示和隐藏“对话框”框架后中断showButton的操作代码。标签的setText(....)更改不会立即对 GUI 产生影响,但框架的setVisible(true)会。然后单步执行 EDT,您会看到setText最终发生在 EDT 计划的更下方。
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;
public class DemonstrateFramePaintEDTPriority {
static class MyFrame extends JFrame {
private JFrame frame;
private JLabel label;
int i = 0;
public MyFrame() {
// Some label strings
final String string[] = new String[] { "label text one",
"label 2222222", "3 3 3 3 3 3 3" };
// Create GUI components.
frame = new JFrame("Dialog");
label = new JLabel("no text set on this label yet");
frame.setSize(500, 200);
frame.setLayout(new FlowLayout());
frame.add(label);
// Add show and hide buttons.
JButton showButton = new JButton("show dialog");
showButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// Set the label text - THIS HAPPENS AFTER frame.setVisible
label.setText(string[i]);
// Select new label text for next time.
i++;
if (i >= string.length) {
i = 0;
}
// Show dialog - THIS HAPPENS BEFORE label.setText
frame.setVisible(true);
}
});
JButton hideButton = new JButton("hide dialog");
hideButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
label.setText("label removed");
frame.setVisible(false);
}
});
setSize(500, 200);
setLayout(new FlowLayout());
add(showButton);
add(hideButton);
}
}
public static void main(String[] args) {
JFrame frame = new MyFrame();
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.setVisible(true);
}
}