了解JFrame的repaint()命令

时间:2015-06-23 14:20:09

标签: java swing

在尝试理解repaint()和paintComponent()的过程中,我在http://docs.oracle.com/javase/tutorial/uiswing/painting/step3.html上看到了这些代码:

import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseMotionAdapter;

public class SwingPaintDemo3 {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI(); 
            }
        });
    }

    private static void createAndShowGUI() {
        System.out.println("Created GUI on EDT? "+
        SwingUtilities.isEventDispatchThread());
        JFrame f = new JFrame("Swing Paint Demo");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        f.add(new MyPanel());
        f.pack();
        f.setVisible(true);
    } 
}

class MyPanel extends JPanel {

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

    public MyPanel() {

        setBorder(BorderFactory.createLineBorder(Color.black));

        addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                moveSquare(e.getX(),e.getY());
            }
        });

        addMouseMotionListener(new MouseAdapter() {
            public void mouseDragged(MouseEvent e) {
                moveSquare(e.getX(),e.getY());
            }
        });

    }

    private void moveSquare(int x, int y) {
        int OFFSET = 1;
        if ((squareX!=x) || (squareY!=y)) {
            repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
            squareX=x;
            squareY=y;
            repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
        } 
    }


    public Dimension getPreferredSize() {
        return new Dimension(250,200);
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);       
        g.drawString("This is my custom Panel!",10,20);
        g.setColor(Color.RED);
        g.fillRect(squareX,squareY,squareW,squareH);
        g.setColor(Color.BLACK);
        g.drawRect(squareX,squareY,squareW,squareH);
    }  
}

我对这些代码的问题是我不理解这条线"重绘(squareX,squareY,squareW + offset,squareH + offset"。首先,我对repaint()的理解它基本上只是调用paint(Graphics g)或paintComponent(Graphics g),你显然不能像普通程序一样调用它,因为你实际上无法输入图形,比如输入一个int或一个字符串但是,这个程序的paintComponent()没有任何额外的输入(也许它会有paintComponent(Graphics g,int squareX,int squareY,int squareW,int squareH)),所以输入在哪里给予重画去......?它用于什么?

3 个答案:

答案 0 :(得分:1)

example cited调用repaint(int x, int y, int width, int height)以在鼠标处理程序中隐式循环中呈现效率。这种repaint()变体的实现要求RepaintManager将由坐标限定的区域添加到其他“应该刷新的组件”的区域。更新区域是两个重绘矩形的 union

如上所述here,这可能会导致技术上违反GUI框架(例如Swing)的single-thread rule。由于Runnable的实例会不断发布到EventQueue,因此读取失败的风险很小。 Profile两者都接近(练习3)来评估利益与风险。

答案 1 :(得分:1)

  

我不懂行

"repaint(squareX, squareY, squareW+offset,squareH+offset". 

该代码用于重绘面板的小矩形,而不是重新绘制整个面板。画一个小区域显然比画一个小区域更有效。

此外,该语句被调用两次。 repaint()方法使用绘制请求调用RepaintManager来重绘两个矩形区域。 RepaintManager将两个请求合并为一个绘制请求,这将再次使代码更有效。

因此,第一个语句用于清除当前位置的Rectangle绘制。然后改变Rectangle的x / y位置并进行第二次repaint()请求,以便可以在其新位置重新绘制Rectangle。

尝试没有第一个重绘(...)语句的代码,你会看到原始的Rectangle没有被完全清除,所以你得到了旧矩形的痕迹。

答案 2 :(得分:0)

Here可以帮助你解决这个问题。

  

public void repaint(int x,              是的,              整数宽度,              int height)重新绘制此组件的指定矩形。

只需调用普通repaint()即可重新绘制该组件,但使用这些参数即可重新绘制该组件的特定矩形