Компонент самописи Java-Swing уменьшает частоту кадров, когда мышь не движется (только в Linux) - PullRequest
0 голосов
/ 29 апреля 2019

Запуск простого Swing-приложения с JPanel, которое регулярно перерисовывается (с помощью таймера или Network-Activity), вызывает методы paint / paintComponent, однако результирующее изображение на экране обновляется только до тех пор, пока мышь движется перед окном.

Воспроизводится с помощью следующего минимального приложения под Ubuntu с X11 и Wayland. Похоже, что не воспроизводится под Windows. Подобное Python-приложение, использующее GTK, не демонстрирует этой проблемы, оно, похоже, очень специфично для Java.

package de.mazdermind;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class Main {

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            JFrame frame = new JFrame();
            frame.setTitle("SwingBackgroundDrawExperiment");

            frame.setSize(800, 600);
            frame.add(new CustomPanel());
            frame.setVisible(true);
        });
    }

    public static class CustomPanel extends JPanel implements ActionListener {

        private int n = 0;

        public CustomPanel() {
            Timer timer = new Timer(20, this);
            timer.start();
        }

        @Override
        protected void paintComponent(Graphics g) {
            System.out.println("painting");
            g.clearRect(0, 0, getWidth(), getHeight());

            g.setColor(Color.RED);
            g.fillRect(0, n % getHeight(), getWidth(), 10);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            n++;
            System.out.println("scheduling repaint on GUI-Thread");
            EventQueue.invokeLater(() -> {
                System.out.println("requesting repaint");
                repaint();
            });
        }
    }
}

Вот пример экрана, демонстрирующий проблему: https://youtu.be/5zLCMVLrd6M

Анимация начинается плавно, но быстро становится неаккуратной (т.е. от 1 кадр / с до 0,5 кадр / с). Он снова становится плавным, пока Мышь движется впереди окна, но в течение секунды она перестает двигаться, анимация снова становится неаккуратной.

Я ожидаю, что анимация будет одинаково быстрой независимо от движения мыши.

Test-Evironment - это стандартная Ubuntu 18.04.2 с OpenJDK 1.8, поставляемая с Ubuntu:

openjdk version "1.8.0_191"
OpenJDK Runtime Environment (build 1.8.0_191-8u191-b12-2ubuntu0.18.04.1-b12)
OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)

1 Ответ

2 голосов
/ 29 апреля 2019

Это, кажется, работает нормально для меня? Сколько времени нужно, чтобы проблемы проявились? Я использую Windows 10.

Кроме того, у меня есть несколько предложений.

Это позволяет вам нормально закрыть окно.

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

вы должны вызвать следующее в методе paintComponent следующим образом.

    super.paintComponent(g);

Затем очистит панель для следующей краски и применить любые цвета по умолчанию к панели

Наконец, в вашем методе actionPerformed вы уже находитесь в EDT, так что вы можете просто позвоните repaint (), и он запланирует это для вас. Не нужно пнуть другого нить.

...