Java 中的图形;不闪屏更新帧

Graphics in Java; Update frame without flashing screen

我写了一些代码,在 JPanel 的中心画了一条线。在 mouseMoved 动作侦听器中不断重绘该线以指向用户的光标。

一切似乎都很好,但在移动光标一段时间后,正在重绘的线开始闪烁并变得完全不一致。

此闪烁是由于我的 PC 性能不佳还是 clearRect() 方法是 'wrong' 所使用的东西造成的?

以上两个原因不能解释为什么只有在光标移动一定量后才开始闪烁。

请随时 运行 下面的代码,让我知道该行是否开始为您闪烁:

import java.awt.Graphics;


public class Frame1 extends javax.swing.JFrame {

    private javax.swing.JPanel jPanel1;
    int x;
    int y;

    public Frame1() {
        initComponents();
        x = jPanel1.getWidth()/2;
        y = jPanel1.getHeight()/2;
    }

    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jPanel1.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                jPanel1MouseDragged(evt);
            }
            public void mouseMoved(java.awt.event.MouseEvent evt) {
                jPanel1MouseMoved(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 1000, Short.MAX_VALUE)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 680, Short.MAX_VALUE)
        );

        getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);

        pack();
    }

    private void jPanel1MouseDragged(java.awt.event.MouseEvent evt) {                                     

    }                                    

    private void jPanel1MouseMoved(java.awt.event.MouseEvent evt) {                                   
        Graphics g = jPanel1.getGraphics();
        g.clearRect(0, 0,jPanel1.getWidth(), jPanel1.getHeight());
        g.translate(x, y);
        g.drawLine(
                0,
                0,
                (int)(120*Math.cos(Math.atan2(evt.getY() - y, evt.getX() - x))),
                (int)(120*Math.sin(Math.atan2(evt.getY() - y, evt.getX() - x)))
        );
    }                                  

    public static void main(String args[])throws Exception {

        Frame1 frame = new Frame1();

        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                frame.setVisible(true);
            }
        });
    }

}

我怀疑有更好的方法来更新线的位置并在不调用 clearRect() 的情况下重新绘制它,如果您知道,我也很想知道。

Graphics g = jPanel1.getGraphics(); 这不是 Swing 中绘画的完成方式。您已经避开了 Swing 组件提供的双缓冲支持。

相反,创建自定义 JPanel 并覆盖它的 paintComponent 方法(确保在进行任何自定义绘制之前调用 super.paintComponent)并在那里执行绘制。

在你的自定义JPanel中,将你的MouseListener添加到其中,当mouseMoved被触发时,更新你需要的状态变量(最后一个点的点和鼠标点) 并调用 repaint

请参阅 Painting in AWT and Swing and Performing Custom Painting 了解有关如何绘画的更多详细信息