Обновление графического интерфейса дает мерцающий эффект

В настоящее время у меня есть JFrame, где на панели содержимого я рисую изображения из игрового цикла со скоростью 60 кадров в секунду. Это отлично работает, но с правой стороны у меня теперь есть больше элементов Swing, для которых я хочу отображать некоторую информацию при выборе определенных частей панели содержимого. Эта часть представляет собой статический графический интерфейс и не использует игровой цикл.

Я обновляю это так:

public class InfoPanel extends JPanel implements Runnable {
    private String titelType = "type: ";
    private String type;
    private JLabel typeLabel;
    private ImageIcon icon;

    public void update() {
        if (this.icon != null)
            this.typeLabel.setIcon(this.icon);

        if(this.type != null || this.type != "")
            this.typeLabel.setText(this.titelType + this.type);
        else
            this.typeLabel.setText("");
    }

    public void run() {
        try {
            Thread.sleep(150);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        this.update();
    }

(этот метод вызывается только тогда, когда игрок действительно двигается, поэтому он вызывается только один раз, а не 60 раз в секунду)

Я заметил, что при вызове этого метода update() из игрового цикла я получаю эффекты мерцания. Я предполагаю, что это связано с тем, что обновление пользовательского интерфейса занимает некоторое время, поэтому я решил поместить его в новую ветку. Это уменьшило мерцание, но не решило его.

Затем я решил дать новому потоку низкий приоритет, так как часть экрана, которая перерисовывается 60 раз в секунду, гораздо важнее. Это снова уменьшило мерцание, но оно все равно произошло. Затем я решил использовать Thread.sleep(150); в новом потоке перед вызовом метода update(), что полностью устранило эффект мерцания в моей системе.

Однако при запуске на других системах это все равно происходит. Не так часто, как раньше (может быть, раз в 20 секунд), но все равно довольно раздражает. По-видимому, простое обновление пользовательского интерфейса в другом потоке не решает проблему.

Любые идеи, как полностью устранить мерцание?


person Bv202    schedule 22.11.2011    source источник
comment
Вы пытались посмотреть на это: stackoverflow.com/q/669979/401667   -  person KristofMols    schedule 22.11.2011


Ответы (2)


Вызовите update() в SwingUtilities.invokeAndWait(), который остановит поток и обновит пользовательский интерфейс в EDT.

person StanislavL    schedule 22.11.2011
comment
Вы начинаете нить. Когда вам нужно что-то изменить в графическом интерфейсе, вы вызываете SwingUtilities.invokeAndWait (ваш код в Runnable здесь) - person StanislavL; 22.11.2011
comment
@Bv202 Bv202, пожалуйста, посмотрите связанный пример в моем ответе о Runnble#Thread, там просто заменить invokeLater на invokeAndWait, требуется добавить броски для InteruptedXxxXxx - person mKorbel; 22.11.2011
comment
Я отредактировал свой вопрос с моим текущим кодом. Есть идеи, что случилось? Спасибо - person Bv202; 22.11.2011
comment
О, неважно, по-видимому, это была просто попытка/улов. Сейчас тестирую, спасибо - person Bv202; 22.11.2011

Проблема в том, что вы используете Thread.sleep(int), который останавливает и замораживает графический интерфейс на EventDispatchTread больше в Параллелизм в Swing, пример, демонстрирующий заморозить графический интерфейс, используя Thread.sleep(int), пример для Runnable#Thread

Если вы хотите отложить что-либо в Swing, лучший способ — реализовать javax. свинг.Таймер

person mKorbel    schedule 22.11.2011