我想我將能夠提供有關paintComponent()
方法和是否我需要使用repaint()
方法都有些幫助/提示,算起來,我不能讓由於某種原因,我的頭圍繞着這些。
基本上,假設您通過擴展JPanel
來創建自定義組件。當你@Override
,paintComponent()
方法,它隱含地被稱爲爲你,所以你永遠不必調用它。所以你在這個方法裏面畫什麼,都會被繪製在你的表面上。例如
public class DrawingPanel extends JPanel {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillOval(x, y, 10, 10);
}
}
當你調用repaint()
你基本上是導致paintComponent
方法隱式調用。所以要回答你的問題,是的如果你想動畫,你將需要調用它,因爲你需要更新paintComponent()方法中的某種變量(如x和y),以查看任何更改圖紙。
你可以看到更多在Performing Custom Painting
不處理實際的動畫,你需要使用一個javax.swing.Timer
。你可以在How to use Swing Timers看到更多。這裏是基本的結構
Timer (int delayInMillis, ActionListener listener)
其中delayInMillis
是蜱之間的延遲時間(在這種情況下,動畫)和ActionListener
監聽「滴答」。調用每個勾號ActionListener
的actionPerformed
。在那裏,您可以將代碼更新用於動畫的任何變量。
因此,例如,在更新X和Y,在actionPerformed
,然後調用repaint()
public class DrawingPanel extends JPanel {
int x = 50;
int y = 50;
public DrawingPanel() {
Timer timer = new Timer(40, new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
x += 5;
y += 5;
repaint();
}
});
timer.start();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillOval(x, y, 10, 10);
}
}
現在,這只是一個簡單的例子。但在你的情況下,你想要動畫一個散點圖。所以你可以做的是有一個列表Point
s和在actionPerformed
你可以添加列表中的拉點並將它們推入另一個要繪製的列表中。所以說你有這個
List<Point> originalPoints;
List<Point> pointsToDraw;
...
@Override
protected void paintComponent(Grapchics g) {
super.paintComponent(g);
for (Point point : pointsToDraw) {
g.fillOval(point.x - 5, point.y - 5, 10, 10);
}
}
基本上所有的點在pointsToDraw
列表將被繪製。最初它將是空的。在計時器中,您可以添加到列表中,直到originalPoints
列表已用盡。例如。
List<Point> originalPoints;
List<point> pointsToDraw;
private int currentIndex = 0;
public DrawingPanel(List<Point> originalPoints) {
this.originalPoints = originalPoints;
pointsToDraw = new ArrayList<>();
Timer timer = new Timer(40, new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
if (currentIndex == originalPoints.size() - 1) {
((Timer)e.getSource()).stop();
} else {
pointsToDraw.add(originalPoints.get(currentIndex));
currentIndex++;
}
repaint();
}
});
timer.start();
}
因此,基本上你只是保持當前的指數。當索引達到原始列表的大小時,您停止定時器。否則,您只需從originalPoints
彈出並推送至pointsToDraw
。對於添加pointsToDraw
的每個點,調用一個repaint()
,並且paintComponent
會有另一個點繪製圓。
結束
UDPATE
我只是重讀你的問題,我想我已經誤解了它。如果你想要繪製所有的點,那麼基本上只有一個列表。並且最初畫出所有要點。每次打勾時,只需刪除第一個索引,將所有其餘索引加到索引上,並在結尾添加一個新索引。雖然這是執行LinkedList
,所以你可能只想使用即