.setVisible (true) немедленная перекраска - PullRequest
5 голосов
/ 12 октября 2011

В коротком методе я скрываю JFrame, используя setVisible (false). Затем я делаю скриншот и восстанавливаю JFrame с помощью setVisible (true).

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

Проблема в том, что после вызова setVisible (true) окно мигает со старым содержимым за доли секунды до вызова paintComponent и отображается обновленное состояние.

Возможно, я мог бы обойти это безобразно, но я хотел знать, есть ли лучшие решения.

Заранее спасибо за любую помощь

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

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;

import javax.swing.JFrame;
import javax.swing.JPanel;

import com.sun.awt.AWTUtilities;
public class Test {

    static boolean flag = false;
    static Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();

    public static void main(String[] args) throws InterruptedException {
        JFrame frame = new JFrame();
        frame.setUndecorated(true);
        AWTUtilities.setWindowOpaque(frame, false);  //draw on a transparent window
        frame.setSize(scrSize.width, scrSize.height);
        frame.setContentPane(new JPanel() {
            protected void paintComponent(Graphics g) 
            {
                if (Test.flag) {
                    g.setColor(Color.RED);
                    g.drawRect(50, 50, scrSize.width - 100, scrSize.height - 100);
                }
                else {
                    g.setColor(Color.GREEN);
                    g.fillOval(50, 50, scrSize.width - 100, scrSize.height - 100);
                }
            }
        });
        frame.setVisible(true); //green oval shown
        Thread.sleep(1000);
        frame.setVisible(false);
        flag = true; // next draw produces red rectangle
        Thread.sleep(1000);
        frame.setVisible(true); // before the next draw, 
                                // you can see a flash of the green oval
    }

}

Ответы [ 2 ]

4 голосов
/ 12 октября 2011

Это связано с тем, что каждое окно AWT имеет изображение вне экрана, которое синхронизируется с изображением на экране. Когда окно отображается, его содержимое рисуется непосредственно из закадрового изображения. Это происходит в потоке инструментария, а не в потоке диспетчеризации событий.

Только после показа окна перерисовывается кадр в потоке отправки событий.

До Java 1.6 в AWT не было двойной буферизации для каждого окна, поэтому вы могли видеть серый фон, который был печально известной проблемой "серого прямоугольника".

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

3 голосов
/ 27 октября 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...