我做了一个程序,用数字解决了一组微分方程,它描述了一个“任意”疾病如何在孤立和恒定的人口中移动,这是我前一段课程的编程任务。我所做的是扩展它是添加一些可以暂停,重置和“播放”模拟的图形组件,以及一些允许我更改方程中某些常量的组件。
所有这些都是编程练习,因为我发现它很有趣,也很有趣,并希望变得更好。
然而,在我被卡住的那一刻,我现在要做的是制作一个非常简单的动画形式。我希望将网格中感染,易感和抵抗物数量的数据可视化为点数。我设法创建了网格,并想知道如何放置点。
我遇到的问题是如何在程序工作时绘制点,我可以在网格中绘制一个点,但只有在创建网格时,就是这样。我需要能够在网格中的特定位置创建一个点,这一直持续到点的数量达到有限数量,比如30.在那个点我想要第一个点,左边的那个,去掉,所有的点都向左移动,并将新点放在网格的最右边,然后重复整个点。
我想我可以通过一些关于paintComponent()
方法的帮助/提示以及是否需要使用repaint()方法来解决这个问题,我无法理解这些问题。原因。我已经阅读了关于Java的课程文献,但是尽管他解释了大多数不同的图形组件的大量部分,但他没有对这些方法说太多,只是你没有要求paintComponent()
方法,它会自动完成。
如果有什么不清楚的地方让我知道,我会尽力澄清它。
提前致谢。
// Fox Mulder
答案 0 :(得分:1)
我想我可以通过一些有关
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
侦听“ticks”之间的延迟时间。每个标记都会调用actionPerformed
的{{1}}。在那里,您可以放置代码来更新用于动画的任何变量。
例如,您在ActionListener
中更新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
你可以从 列表中添加拉取点并将它们推送到另一个要绘制的列表中。所以说你有这个
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
所以basicall你只保留一个当前索引。当索引达到原始列表的大小时,您将停止计时器。否则,您只需从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()
会有另一个点来绘制圆圈。
结束
<强> UDPATE 强>
我只是重读了你的问题,我想我已经误解了它。如果你想要绘制所有点,那么基本上只有一个列表。并初步绘制所有要点。每次勾选时,只需删除第一个索引,将所有其余索引推进到索引,然后添加一个新索引。虽然这是LinkedList
的实现,所以您可能只想使用