Проблема
Я создаю диалоговое окно на качелях (JRE 6, обновление 10, Ubuntu linux). Когда пользователь закончил использовать диалоговое окно, оно скрыто. Когда пользователи нажимают кнопку в другом кадре, метка на блоке изменяется в соответствии с кнопкой, а затем блок снова отображается.
Проблема, с которой я столкнулся, заключается в том, что поле отображается до того, как метка меняется, хотя программно я звоню в обратном порядке. Это приводит к тому, что появляется окно, за которым следует изменение метки, которое выглядит «глючно» на нашем медленном целевом HW. Похоже, что EDT планирует кадр setVisible (true) перед меткой setText (....) ; это дает приоритет этому вызову. Есть ли способ заставить 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);
}
}