Java 是什么导致此代码重新绘制自身?

Java 是什么导致此代码重新绘制自身?,java,swing,paintcomponent,Java,Swing,Paintcomponent,在下面的代码中,箭头键用于绘制一条线,如蚀刻草图中所示(但您必须首先调整窗口大小,以便在正确的时间触发面板的聚焦请求——这可能是另一个时间的问题)。图形命令g.drawLine()出现在keyPressed()函数中,不显式调用repaint(),但当按下箭头键时,图像会自动更新。为什么呢?我看过的所有文档都只谈到JPanel在调整大小或打开时自动重新绘制自身 import java.awt.event.*; import java.awt.*; import javax.swing.*; p

在下面的代码中,箭头键用于绘制一条线,如蚀刻草图中所示(但您必须首先调整窗口大小,以便在正确的时间触发面板的聚焦请求——这可能是另一个时间的问题)。图形命令g.drawLine()出现在keyPressed()函数中,不显式调用repaint(),但当按下箭头键时,图像会自动更新。为什么呢?我看过的所有文档都只谈到JPanel在调整大小或打开时自动重新绘制自身

import java.awt.event.*;
import java.awt.*;
import javax.swing.*;

public class Etch extends JPanel implements KeyListener{
    public int xPrev, yPrev, xNew, yNew, inc;

    public Etch(int start){
        xPrev = start;
        yPrev = start;
        xNew = start;
        yNew = start;
        inc = 10;
        addKeyListener(this);


    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        this.requestFocusInWindow();
    }


    public static void main(String[] args)
    {
        JFrame w = new JFrame("Keyboard");
        w.setBounds(100, 100, 600, 600);
        w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Etch panel = new Etch(200);
        panel.setFocusable(true);
        panel.setBackground(Color.RED);

        Container c = w.getContentPane();
        c.add(panel);

        w.setResizable(true);
        w.setVisible(true);

    }

    public void keyPressed(KeyEvent e){
        int code = e.getKeyCode();


        if (code == KeyEvent.VK_UP){
            xPrev = xNew;
            yPrev = yNew;
            yNew -= inc;

        }
        if (code == KeyEvent.VK_DOWN){
            xPrev = xNew;
            yPrev = yNew;
            yNew += inc;

        }
        if (code == KeyEvent.VK_LEFT){
            xPrev = xNew;
            yPrev = yNew;
            xNew -= inc;
        }
        if (code == KeyEvent.VK_RIGHT){
            xPrev = xNew;
            yPrev = yNew;
            xNew += inc;
        }

        Graphics g = this.getGraphics();
        g.setColor(Color.BLUE);
        g.drawLine(xPrev, yPrev, xNew, yNew);
    }

    // Not used but required by the KeyListener interface
    public void keyReleased (KeyEvent e) { }

    public void keyTyped (KeyEvent e) { }
}

  • this.requestFocusInWindow()
    paintComponent
    方法中是一个坏主意。绘制应绘制当前状态,且决不更改零部件的状态
  • getGraphics
    不是Swing中的绘画方式。自定义绘制应在
    paintComponent
    方法的上下文中完成。有关详细信息,请参阅和
  • 考虑在
    KeyListener
    上使用键绑定,因为您可以控制触发键事件所需的焦点级别。有关更多详细信息,请参阅
请记住,在Swing中您无法控制绘制过程,绘制周期可以由任意数量的事件触发,其中大多数事件您实际上无法控制。尝试在流程内工作,而不是在流程外工作


首先创建
java.awt.Point
列表。发生关键事件时,将每个点添加到
列表中。使用
paintComponent
列表上迭代,并在
点之间绘制线条。

this.requestFocusInWindow()
paintComponent
方法中是一个坏主意。绘制应该绘制当前状态,并且永远不要更改组件的状态。感谢您对如何改进代码的评论。鉴于我发布的代码不是实现其目的的好方法,我仍然对它的实际工作方式感到困惑,即是什么导致屏幕图像在每次箭头键事件后更新。对图形对象的任何更改是否会导致重新绘制屏幕?对我来说,这似乎不太可能,每次按下一个键时都会重新绘制屏幕的想法也是如此。这是可行的,因为Swing使用被动绘制程序,也就是说,只有当重新绘制管理器认为需要时才会调用paintComponent方法。这允许您使用getGraphics绘制到绘制周期的最后一个已知结果,这也是再次调用paintComponent时将其清除的原因。绘制应该在paintComponent方法的范围内完成,这样,您就知道何时需要更新屏幕。您的关键事件应该调用repaint来请求更新UI