軟件構造實驗二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足夠聰明,可以獲取該信息並重新繪製這些片段。
好了,疑惑解決!