Отменяет ли AWT / Swing операцию рисования, если монитор выключен? - PullRequest
11 голосов
/ 28 мая 2011

У меня проблема с Swing, которая возникает только тогда, когда монитор компьютера выключен, но мое приложение Swing продолжает работать в фоновом режиме.Кажется, что когда монитор выключен, Swing / AWT отменяет все операции рисования, что приводит к ряду проблем с отображением в графическом интерфейсе, которые видны, как только монитор снова включается.

Например, когда яВыключите монитор с помощью пользовательской функции JNI, а затем откройте простое диалоговое окно сообщения. При повторном включении монитора диалоговое окно будет пустым:

Blank message dialog

Но после правильнойследующий перекрас:

Correctly painted message dialog

Это ожидаемое поведение 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");
            }
        });
    }
}

IЯ использую 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();
            }
        });
    }
}

Перед выключением монитора я вижу:

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

РЕДАКТИРОВАТЬ 3: Сообщено в Oracleкак Ошибка ID 7049597 .

Ответы [ 2 ]

2 голосов
/ 29 мая 2011

Затем я запустил программу и остановился перемещение мыши / набор текста. После одного минуту экран выключился. я ждал еще 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();
            }
        });
    }
}
0 голосов
/ 29 мая 2011

Проблема, вероятно, больше связана с тем, как он перерисовывается при включении экрана, а не с тем, что происходит, когда он выключен. Вы можете проверить, запустив рекордер экрана.

...