软件构造实验二P3部分,如果想要实现一个漂亮的应用,必须用到GUI设计,这又涉及到我的知识盲区了,怎么看,看官方文档和官方资料。
在学习Graphics类时,对于其中的repaint()方法,有了一定的认识。
想要实现如下功能:
1.在图形化界面中输出一段话:This is my custom Panel!
2.初始化一个小红正方形的位置,之后伴随鼠标的拖拽或者点击,更新小红正方形的位置。
实现代码:(注意其中的repaint())
import javax.swing.SwingUtilities;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Panel;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class SwingPaintDemo1 {
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.pack();
f.add(new MyPanel());
f.setVisible(true);
}
}
class MyPanel extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
private int squareX = 50;
private int squareY = 50;
private int squareW = 50;
private int squareH = 50;
public MyPanel() {
setBorder(BorderFactory.createLineBorder(Color.red));
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());
}
});
}
public void moveSquare(int x, int y) {
int OFFSET = 1;
if ((squareX != x) || (squareX != y)) {
repaint(squareX, squareY, squareW + OFFSET, squareH + OFFSET);
squareX = x;
squareY = y;
repaint(squareX, squareY, squareW + OFFSET, squareH + OFFSET);
}
}
//这里返回了想要的大小,所以在SwingPaintDemo1中不要要指定大小了
@Override
public Dimension getPreferredSize() {
return new Dimension(250,200);
}
//所有的定制绘画产生的地方
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
//所有作为该图形对象的方法的参数出现的坐标都被认为是相对于该图形对象在调用该方法之前的转换原点的。
// Draw Text
g.drawString("This is my custom Panel!",100,200);
g.setColor(Color.red);
g.fillRect(squareX, squareY, squareW, squareH);
g.setColor(Color.black);
g.drawRect(squareX, squareY, squareW, squareH);
// repaint();
}
}
现在的代码可以正确实现目标功能。
点击鼠标之后,小红正方形的位置发生改变。
moveSquare方法中的repaint()方法调用了两次,有没有感觉很奇怪呢?明明要更新小红正方形的位置,为什么还要repaint一遍原来的正方形呢?
通过查阅资料,可以看到repaint()方法的细节:
- repaint()方法可以添加参数(如上述代码所示),也可以不加参数。添加参数时,界面只会更新参数限定的区域,不添加参数时,更新整个界面。所以,添加参数时,该方法更高效。
- repaint()的调用过程:repaint()->update() ->paint()。看到这里是不是更疑惑了?moveMouse方法实现的效果为什么不是这样?
根据代码,效果确实应该是这样,查阅了一些博客都没有很好的解释。最后还是官方文档解决了这个疑惑。
见下面的解释:
好啦,我来帮助大家翻译一下:因为我们是手动设置剪辑的,所以我们的moveSquare方法调用repaint方法不是一次,而是两次。第一次调用告诉Swing重新绘制组件的区域,该区域以前是正方形的位置(继承的行为使用UI委托用当前的背景颜色填充该区域)。第二次调用将绘制组件的区域,该区域是正方形当前所在的位置。值得注意的重要一点是,尽管我们在同一事件处理程序中连续两次调用repaint,但Swing足够聪明,可以获取该信息并重新绘制这些片段。
好了,疑惑解决!