Java swing - super.paintcomponent(g) - repaint()

时间:2013-11-19 22:26:34

标签: java swing

我有两个类如下,在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);


}


}

2 个答案:

答案 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}}的控制之下,它将决定什么以及何时应该绘制。当它决定需要进行更新时,它会在事件队列上放置一个“绘制”事件,该事件队列将在事件调度线程的某个时间处理。这意味着,在大多数情况下,绘画不是立竿见影的......