繁体   English   中英

当鼠标不移动时,Java-Swing自绘组件会降低帧速率(仅在Linux上)

[英]Java-Swing self-painting Component reduces framerate when the Mouse is not Moving (only on Linux)

使用JPanel运行一个简单的Swing应用程序并定期重绘自身(通过Timer或Network-Activity),会触发paint / paintComponent方法,但是只要鼠标在移动,屏幕上生成的图像就只会更新在窗前。

在具有X11和Wayland的Ubuntu下,以下最小应用程序可以重现此问题。 在Windows下似乎无法再现。 使用GTK的类似Python应用程序不会出现此问题,它似乎非常针对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

动画开始流畅,但很快就变得马虎(即介于1fps至0.5fps之间)。 只要鼠标在窗口的前面移动,它就会再次变得平滑,但是在第二秒内它停止移动,动画又变得草率。

我希望动画能够独立于鼠标运动而同样快。

Test-Evironment是Ubuntu 18.04.2的一个原始版本,Ubuntu随附了OpenJDK 1.8:

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)

这似乎对我来说很好? 问题显现需要多长时间? 我正在运行Windows 10。

另外,我确实有一些建议。

这使您可以正常关闭窗口。

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

您应该在paintComponent方法中调用以下第一件事。

    super.paintComponent(g);

然后它将清除面板上的下一种油漆并将所有默认颜色应用于面板

最后,在actionPerformed方法中,您已经在EDT中,因此您只需调用repaint()即可为您安排时间。 无需启动另一个线程。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM