Java 如果监视器关闭,AWT/Swing是否取消喷漆操作?

Java 如果监视器关闭,AWT/Swing是否取消喷漆操作?,java,swing,awt,repaint,Java,Swing,Awt,Repaint,我遇到了一个Swing问题,该问题仅在计算机显示器关闭时发生,但我的Swing应用程序仍在后台运行。似乎每当监视器关闭时,Swing/AWT都会取消所有绘制操作,从而导致GUI中出现许多显示问题,只要监视器重新打开,这些问题就可以看到 例如,当我使用自定义JNI函数关闭监视器并随后打开一个简单的消息对话框时,当监视器重新打开时,消息对话框为空: 但在下一次重新喷漆后,它会正确喷漆: 这是Swing的预期行为吗?是否有方法指示Swing在显示器断电的情况下继续绘制屏幕 编辑:这是一个SSCCE

我遇到了一个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位Windows7家庭高级SP1和64位Java1.6.0\u24

编辑2:这里是另一个程序,我体验到了“取消绘制操作”的效果:

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

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


编辑3:向Oracle报告为。

问题可能更多地与屏幕打开时如何重新绘制有关,而不是与屏幕关闭时发生的情况有关。您可以通过运行屏幕记录器进行检查

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

以你的例子来说,我在我的(非Windows)平台上看不到这一点。您可以尝试下面的示例,该示例应在唤醒时激活
WINDOW\u
和睡眠时禁用
WINDOW\u
之间交替。如果是这样,您可以在
windowActivated()
中扩展
JDialog
repaint()


我无法重现这种效果。请提供一份说明问题的报告。什么平台?@trashgood:提供SSCCE有点困难,因为我的自定义JNI例程关闭监视器是专有的。不过,我会看看我能想出什么。我使用的是64位Windows 7 Home Premium SP1和64位Java 1.6.0_24。请编写在手动启动睡眠模式时再现效果的最小示例。另请参见。@trashgood:我添加了一个SSCCE。为了使用它,我临时更改了电源计划设置,在不活动1分钟后关闭显示器。然后我启动程序,停止移动鼠标/打字。一分钟后,屏幕关闭。我又等了20秒才移动鼠标。显示器又打开了,我看到一个空白的信息对话框。我在顶部选中了一个程序,将其最小化,然后看到对话框被正确绘制。@垃圾神我认为这个问题是关于一致性的,而不是关于本机操作系统中的电源模式(对于今天的操作系统)+1尽管“对话事件测试”对话框在监视器断电时没有收到窗口停用事件,有趣的是,如果在监视器关闭后打开“对话框事件测试”对话框,我看不到“取消的绘制操作”的效果。但是,如果我替换
new DialogEventTest().display()带有
JOptionPane.showMessageDialog(空,“测试”),那么我就知道问题了。@mKorbel:谢谢!我也想知道并发性,但这个例子似乎是正确的@Joseph Trebbien:我隐约记得一个Windows特有的此类问题,只有当JOptionPane在睡觉时出现时才会出现。扩展
JDialog
是否是一种可能的解决方法?我猜没有要接收的
窗口被激活
@Joseph Trebbien-hmmm它看起来像你或@mKorbel:我不这么认为。我的应用程序完全是用Swing编写的,但我发布的SSCCE也总是有这个问题。
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();
            }
        });
    }
}
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();
            }
        });
    }
}