我遇到了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();
}
});
}
}
在显示器关闭之前,我看到:
关闭显示器后,标签背景颜色在背景中变为黄色。然后我移动鼠标重新打开显示器。对话框在视觉上保持不变。只有在我强制重绘之后(例如通过ALT-TABbing)我才能看到黄色:
编辑3:以Bug ID 7049597向Oracle报告。
答案 0 :(得分:2)
然后我启动了程序并停止了 移动鼠标/打字。一个之后 一分钟,屏幕关闭。一世 又等了20秒才动了 老鼠。显示器重新打开并且 我看到一个空白的消息对话框。
使用您的示例,我在我的(非Windows)平台上看不到这一点。您可以尝试以下示例,该示例应在唤醒时WINDOW_ACTIVATED
和睡眠时WINDOW_DEACTIVATED
之间切换。如果是这样,您可以在JDialog
中扩展repaint()
和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();
}
});
}
}
答案 1 :(得分:0)
这个问题可能更多地与它在屏幕亮起时的重新绘制有关,而不是在它关闭时发生的事情。您可以通过运行屏幕录像机进行检查。