Разве AWT/Swing отменяет операции рисования, если монитор выключен?
У меня возникла проблема с 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");
}
});
}
}
Я использую 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.
Ответы
Ответ 1
Затем я запустил программу и остановился перемещая мышь/ввод текста. После одного минуты, экран выключен. я ждал еще 20 секунд, чтобы переместить мышь. Монитор снова включился и Я видел диалоговое окно с пустым сообщением.
Используя ваш пример, я не вижу этого на моей (не Windows) платформе. Вы можете попробовать пример ниже, который должен чередоваться между WINDOW_ACTIVATED
on wake и 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();
}
});
}
}
Ответ 2
Проблема, вероятно, имеет больше общего с тем, как она перерисовывается, когда экран появляется, а не то, что происходит во время его отключения. Вы можете проверить, запустив экранный рекордер.