如果显示器关闭,AWT / Swing是否取消绘画操作?

我遇到Swing问题,只有在计算机显示器电源关闭时才会出现,但我的Swing应用程序继续在后台运行。 似乎每当显示器关闭时,Swing / AWT都会取消所有绘画操作,导致GUI中的一些显示问题在显示器重新打开后立即可见。

例如,当我使用自定义JNI函数关闭监视器并随后打开一个简单的消息对话框时,当监视器重新打开时,消息对话框为空:

空白消息对话框

但它在下次重绘后正确绘制:

正确绘制消息对话框

这是Swing的预期行为吗? 有没有办法指示Swing即使显示器电源关闭也能继续绘制到屏幕上?

编辑:这是一个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。

编辑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(); } }); } } 

在显示器关闭之前,我看到:

在监视器关闭之前,DialogTest对话框的屏幕截图

关闭显示器后,标签背景颜色在背景中变为黄色。 然后我移动鼠标重新打开显示器。 对话框在视觉上保持不变。 只有在我强制重绘之后(例如通过ALT-TABbing)我才能看到黄色:

DialogTest对话框的屏幕截图,其中主标签具有黄色背景

编辑3:向Oracle报告错误ID 7049597 。

然后我启动程序并停止移动鼠标/打字。 一分钟后,屏幕关闭。 我又等了20秒才移动鼠标。 显示器重新打开,我看到一个空白的消息对话框。

使用您的示例,我在我的(非Windows)平台上看不到这一点。 您可以尝试下面的示例,该示例应在唤醒时WINDOW_ACTIVATED和睡眠时WINDOW_DEACTIVATED之间WINDOW_DEACTIVATED 。 如果是这样,你可以在windowActivated()扩展JDialogrepaint() windowActivated()

 import java.awt.EventQueue; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.AbstractAction; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; /** @see http://stackoverflow.com/questions/6163606 */ public class DialogEventTest extends JDialog { public DialogEventTest() { this.setLayout(new GridLayout(0, 1)); this.add(new JLabel("Dialog event test.", JLabel.CENTER)); this.add(new JButton(new AbstractAction("Close") { @Override public void actionPerformed(ActionEvent e) { DialogEventTest.this.setVisible(false); DialogEventTest.this.dispatchEvent(new WindowEvent( DialogEventTest.this, WindowEvent.WINDOW_CLOSING)); } })); } private static class WindowHandler extends WindowAdapter { @Override public void windowActivated(WindowEvent e) { System.out.println(e); } @Override public void windowDeactivated(WindowEvent e) { System.out.println(e); } } private void display() { this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); this.addWindowListener(new WindowHandler()); this.pack(); this.setLocationRelativeTo(null); this.setVisible(true); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { new DialogEventTest().display(); } }); } } 

这个问题可能更多地与它在屏幕亮起时如何重新绘制有关,而不是在它关闭时发生的情况。 您可以通过运行屏幕录像机进行检查。