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