我有两个类如下,在MyPanel类中,我已经覆盖了paintComponent方法,将我自己的“绘图”添加到JPanel。我已经调用了super.paintComponent(g),据我所知,当我使用自己的inhertied方法实现时,我也覆盖了此方法的标准“隐藏”功能。我明白如果我想在myPanel上使用类似setBackground / setBorder的方法,我必须从扩展类调用paintComponent方法,使其以自己的标准方式工作 (油漆背景,油漆寄宿生等)。
所以在我看来,每当我按下鼠标按钮时,我都会调用我的moveSquare方法,它会调用重绘方法。当调用repaint方法时,程序转到覆盖的paintComponent方法。我知道当我使用
时repaint(squareX, squareY, squareW, squareH);
在moveSquare方法中,它只重绘红色方块(背景不会重新绘制),这就是为什么我会看到我面板上的每个红色方块。我知道如果我在第一次调用中使用repaint()然后用这样的参数重新绘制:
repaint();
squareX=x;
squareY=y;
repaint(squareX, squareY, squareW, squareH);
它将重绘背景然后绘制一个正方形,所以我将只能看到我面板上最后一个红色的正方形。我不明白为什么双重调用带有参数的重绘方法:
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);
}
}
答案 0 :(得分:1)
这是因为当你致电repaint()
时,它不会立即发生;它将被放入事件调度线程并稍后调用。如果连续调用多次重绘,它可能会重新绘制矩形的并集。
因此,当您第一次调用重绘时,它将排队以绘制您指定的矩形。然后你更新方块的坐标,然后你绘制然后你用新的矩形排队重绘。然后它结合两个并将绘制他们的矩形的联合。当重绘执行时,它将清除背景该地区然后画广场。
在System.out.printf("dirty region = %s%n",g.getClipBounds());
中插入paintComponent ()
以查看正在绘制的矩形
答案 1 :(得分:1)
paintComponent
代表ComponentUI#update
,将Graphics
上下文的颜色设置为组件背景颜色并填充0, 0, c.getWidth(), c.getHeight()
(其中c
是对repaint
的引用组件被涂上了。)
基本上,这意味着,即使您使用repaint(x, y, width, height)
或Graphics
,背景也会开始全面更新。
不同之处在于,repaint
剪辑会发生变化。调用repaint(x, y, width, height)
时,剪辑将是组件的大小,使用RepaintManager
时,剪辑形状将与您传递的剪辑形状相同。
您可能需要查看Painting in AWT and Swing了解更多详情。
请记住,在Swing中绘画是在{{1}}的控制之下,它将决定什么以及何时应该绘制。当它决定需要进行更新时,它会在事件队列上放置一个“绘制”事件,该事件队列将在事件调度线程的某个时间处理。这意味着,在大多数情况下,绘画不是立竿见影的......