如果监视器关闭,AWT/Swing 是否会取消绘画操作?

2023-11-22

我遇到了 Swing 问题,该问题仅在计算机显示器关闭时出现,但我的 Swing 应用程序继续在后台运行。似乎只要显示器关闭,Swing/AWT 就会取消所有绘画操作,从而导致 GUI 中出现许多显示问题,一旦显示器重新打开,这些问题就会显现出来。

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

Blank message dialog

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

Correctly painted message dialog

这是 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();
            }
        });
    }
}

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

Screenshot of the dialog of DialogTest before the monitor shuts off

显示器关闭后,标签背景颜色将更改为黄色。然后我移动鼠标以重新打开显示器。该对话框在视觉上没有变化。只有在我强制重新绘制(例如通过 ALT-TABbing)后,我才会看到黄色:

Screenshot of the dialog of DialogTest where the main label has a yellow background

EDIT 3:向 Oracle 报告为错误号 7049597.


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

使用您的示例,我在我的(非 Windows)平台上没有看到这一点。您可以尝试下面的示例,该示例应该在WINDOW_ACTIVATED唤醒时和WINDOW_DEACTIVATED睡觉时。如果是这样,您可以延长JDialog and repaint() in 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();
            }
        });
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果监视器关闭,AWT/Swing 是否会取消绘画操作? 的相关文章

随机推荐