我遇到了 Swing 问题,该问题仅在计算机显示器关闭时出现,但我的 Swing 应用程序继续在后台运行。似乎只要显示器关闭,Swing/AWT 就会取消所有绘画操作,从而导致 GUI 中出现许多显示问题,一旦显示器重新打开,这些问题就会显现出来。
例如,当我使用自定义 JNI 函数关闭监视器并随后打开一个简单的消息对话框时,当监视器重新打开时,该消息对话框为空白:
但在下次重新绘制后它会正确绘制:
这是 Swing 的预期行为吗?有没有办法指示 Swing 在显示器关闭的情况下继续绘制到屏幕上?
EDIT:这是一个 SSCCE:
package test;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
public class App {
public static void main(String[] args) throws Throwable {
System.out.println("***** Please turn off the monitor in the next 70 seconds *****");
Thread.sleep(1000L * 70);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JOptionPane.showMessageDialog(null, "Test");
}
});
}
}
我使用的是 64 位 Windows 7 Home Premium SP1 和 64 位 Java 1.6.0_24。
EDIT 2:这是我体验“取消绘画操作”效果的另一个程序:
package test;
import static com.mycompany.Util.turnOffMonitors;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class DialogTest extends JDialog {
private final JLabel label;
public DialogTest() {
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
label = new JLabel("Test", JLabel.CENTER);
label.setOpaque(true);
Container contentPane = getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(BorderLayout.CENTER, label);
this.setPreferredSize(new Dimension(200, 110));
pack();
setLocationRelativeTo(null);
setVisible(true);
Thread t = new Thread() {
@Override
public void run() {
turnOffMonitors();
try {
Thread.sleep(3000L);
} catch (InterruptedException ex) { }
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
label.setBackground(Color.YELLOW);
}
});
}
};
t.start();
}
public static void main(String[] args) throws Throwable {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new DialogTest();
}
});
}
}
在显示器关闭之前,我看到:
显示器关闭后,标签背景颜色将更改为黄色。然后我移动鼠标以重新打开显示器。该对话框在视觉上没有变化。只有在我强制重新绘制(例如通过 ALT-TABbing)后,我才会看到黄色:
EDIT 3:向 Oracle 报告为错误号 7049597.