图形组件

时间:2014-06-19 16:31:24

标签: java swing graphics plot real-time

我做了一个程序,用数字解决了一组微分方程,它描述了一个“任意”疾病如何在孤立和恒定的人口中移动,这是我前一段课程的编程任务。我所做的是扩展它是添加一些可以暂停,重置和“播放”模拟的图形组件,以及一些允许我更改方程中某些常量的组件。

所有这些都是编程练习,因为我发现它很有趣,也很有趣,并希望变得更好。

然而,在我被卡住的那一刻,我现在要做的是制作一个非常简单的动画形式。我希望将网格中感染,易感和抵抗物数量的数据可视化为点数。我设法创建了网格,并想知道如何放置点。

我遇到的问题是如何在程序工作时绘制点,我可以在网格中绘制一个点,但只有在创建网格时,就是这样。我需要能够在网格中的特定位置创建一个点,这一直持续到点的数量达到有限数量,比如30.在那个点我想要第一个点,左边的那个,去掉,所有的点都向左移动,并将新点放在网格的最右边,然后重复整个点。

我想我可以通过一些关于paintComponent()方法的帮助/提示以及是否需要使用repaint()方法来解决这个问题,我无法理解这些问题。原因。我已经阅读了关于Java的课程文献,但是尽管他解释了大多数不同的图形组件的大量部分,但他没有对这些方法说太多,只是你没有要求paintComponent()方法,它会自动完成。

如果有什么不清楚的地方让我知道,我会尽力澄清它。

提前致谢。

// Fox Mulder

1 个答案:

答案 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的实现,所以您可能只想使用