【问题标题】:Understanding JFrame's repaint() command了解 JFrame 的 repaint() 命令
【发布时间】:2015-06-23 14:20:08
【问题描述】:

在尝试理解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);
    }  
}

我对这些代码的疑问是我不理解“repaint(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)),那么重绘的输入去哪里了......?它是用来做什么的?

【问题讨论】:

标签: java swing


【解决方案1】:

我不明白这行

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

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

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

所以第一个语句用于清除矩形在其当前位置的绘制。然后 Rectangle 的 x/y 位置发生变化,并发出第二个 repaint() 请求,以便可以在新位置重新绘制 Rectangle。

尝试不使用第一个 repaint(...) 语句的代码,您会发现原始 Rectangle 并未完全清除,因此您会看到旧 Rectangle 的痕迹。

【讨论】:

    【解决方案2】:

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

    here 所述,这可能会导致对 GUI 框架(如 Swing)常见的single-thread rule 的技术违规。因为Runnable 的实例不断发布到EventQueue,读取失败的风险很小。 Profile 两种方法(练习 3)来评估收益与风险。

    【讨论】:

      【解决方案3】:

      Here 可以帮助您。

      公共无效重绘(int x, 整数, 整数宽度, int height) 重绘该组件的指定矩形。

      调用普通的repaint() 只会重绘组件,但使用这些参数您正在重绘该组件的特定矩形

      【讨论】:

        猜你喜欢
        • 2017-01-18
        • 2011-09-18
        • 2014-11-07
        • 2011-10-04
        • 2018-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多