JavaSwing-super.paintcomponent(g)-repaint()

JavaSwing-super.paintcomponent(g)-repaint(),java,swing,Java,Swing,我有两个类,如下所示,在MyPanel类中,我重写了paintComponent方法,将我自己的“绘图”添加到JPanel。我之所以调用super.paintComponent(g),是因为据我所知,当我使用自己的继承方法实现时,我还覆盖了该方法的标准“隐藏”功能。我明白,如果我想在myPanel上使用像setBackground/setboorder这样的方法,我必须从扩展类中调用paintComponent方法,使其以自己的标准方式工作 (绘制背景、绘制边框等) 所以在我看来,每次我按下鼠标

我有两个类,如下所示,在MyPanel类中,我重写了
paintComponent
方法,将我自己的“绘图”添加到
JPanel
。我之所以调用super.paintComponent(g),是因为据我所知,当我使用自己的继承方法实现时,我还覆盖了该方法的标准“隐藏”功能。我明白,如果我想在myPanel上使用像setBackground/setboorder这样的方法,我必须从扩展类中调用paintComponent方法,使其以自己的标准方式工作 (绘制背景、绘制边框等)

所以在我看来,每次我按下鼠标按钮时,我都会调用moveSquare方法,它会调用repaint方法。调用repaint方法时,程序将转到重写的paintComponent方法。我知道当我使用

repaint(squareX, squareY, squareW, squareH);
在moveSquare方法中,它将只重新绘制红方块(背景将不会重新绘制),这就是为什么我将看到面板上的每个红方块。我知道如果我在第一次调用中使用repaint(),然后使用如下参数重新绘制:

                    repaint();
        squareX=x;
        squareY=y;
        repaint(squareX, squareY, squareW, squareH);
它将重新绘制背景,然后绘制一个正方形,因此我只能看到面板上最后一个红色绘制的正方形。我不明白的是,为什么要使用参数双重调用repaint方法:

                    repaint(squareX, squareY, squareW, squareH);
        squareX=x;
        squareY=y;
        repaint(squareX, squareY, squareW, squareH);
将首先绘制一个带有背景颜色的正方形,然后是红色的正方形(其行为类似于我在没有参数的情况下调用repaint,然后使用参数重新绘制)

很抱歉这么长时间的解释,但我想如果你愿意的话,我会更容易指出我的错误 我将解释我认为它应该如何工作

SwingMoveSquareDemo类

public class SwingMoveSquareDemo {

public static void main(String[] args) {

    SwingUtilities.invokeLater(new Runnable(){

                    public void run(){
                        System.out.println("GUI started");
                        createGUI();

                    }

                    });


}

public static void createGUI(){

    JFrame f = new JFrame("Move square demo");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.add(new MyPanel());

    f.pack();
    f.setVisible(true);


}





}
MyPanel类

public class MyPanel extends JPanel {

private int squareX=1;
private int squareY=1;
private int squareW=20;
private int squareH=20;

public MyPanel(){

    setBackground(Color.GRAY);
    setBorder(BorderFactory.createLineBorder(Color.WHITE));
    setPreferredSize(new Dimension(400,250));


    addMouseListener(new MouseAdapter() {
        public void mousePressed(MouseEvent e) {
            System.out.println("mouspressed");
            moveSquare(e.getX(),e.getY());
        }
    });




}

private void moveSquare (int x, int y){


            repaint(squareX, squareY, squareW, squareH);
        squareX=x;
        squareY=y;
        repaint(squareX, squareY, squareW, squareH);





}   



public void paintComponent(Graphics g){

    super.paintComponent(g);

    System.out.println("paint component");

    g.setColor(Color.RED);

    g.fillRect(squareX, squareY, squareW, squareH);


}


}

这是因为当您调用
repaint()
时,它不会立即发生;它将放在事件分派线程上,稍后调用。此外,如果您连续调用多个重绘,它可能会重绘其矩形的并集

因此,当您第一次调用repaint时,它将排队绘制您指定的矩形。然后更新正方形的坐标,然后绘制,然后将重新绘制与新矩形一起排队。然后,它将两者合并,并绘制它们的矩形的并集。执行重新绘制时,它将清除区域的背景,然后绘制正方形


插入
System.out.printf(“脏区域=%s%n”,g.getClipBounds())
paintComponent()
中查看正在绘制的矩形

paintComponent
委托给
ComponentUI#update
,它将
图形
上下文的颜色设置为组件背景色,并填充
0,0,c.getWidth(),c.getHeight()
(其中
c
是指已涂漆的部件)

基本上,这意味着,即使您使用
repait
repait(x,y,width,height)
,背景也会开始完全更新

不同之处在于,
图形
剪辑会更改。调用
重新绘制
时,剪辑将是组件的大小,使用
重新绘制(x、y、宽度、高度)
时,剪辑形状将与传递给它的值相同

您可能需要查看更多详细信息


请记住,Swing中的绘制由
repaitmanager
控制,它将决定绘制内容和时间。当它决定需要进行更新时,它将放置一个“绘制”事件发送到事件队列上,该事件将在将来某个时间由事件调度线程处理。这意味着,在大多数情况下,绘制不是立即进行的…

因此,如果我理解正确,当事件队列处理这两个重绘(x、y、宽度、高度)时他知道剪辑将被更改,他足够聪明,可以在第一次重新绘制调用中重新绘制背景和跳过fillRect,并在第二次重新绘制调用中执行这两个操作?在处理重新绘制时,您已经更改了
squareX
squareY
值。重新绘制将在之后进行de>mouseClicked
方法已经发生,因为它也由EDT处理…是的,但我仍然不明白一件事,在处理mouseClicked两个重新绘制后,它们都是相同的(除了剪辑),我认为它应该在旧剪辑上绘制背景(paintComponent调用),在旧剪辑上fillRect。下一次重新绘制应该在新剪辑上绘制背景(paintComponent调用),并在新剪辑上fillRect,但不是这样,而是这样做的:第一次重新绘制(x,y,w,h)在x,y,w,h剪辑上绘制背景新x,y第二次重新绘制(x,y,w,h)在新x,y,w,h剪辑上绘制背景(是否?)在新的x,y,w,h clips上绘制rect如果您尝试在paintComponent方法中输出squareX和squareY值,我想您会发现两个调用将具有相同的值;)