Java 图形组件

Java 图形组件,java,swing,graphics,plot,real-time,Java,Swing,Graphics,Plot,Real Time,我做了一个程序,用数值方法求解一组微分方程,描述了一种“任意”疾病如何在一个孤立的、恒定的人群中运动,这是我前一段时间上的一门课的编程作业。我所做的扩展是添加一些可以暂停、重置和“播放”模拟的图形组件,以及一些允许我更改方程式中某些常量的组件 所有这些都是编程方面的练习,因为我觉得它很有趣、令人兴奋,并且希望变得更好 然而,目前我陷入困境,我现在想做的是制作一个非常简单的动画形式。我想将网格中感染者、易感者和抵抗者数量的数据可视化为点。我设法创建了网格,并对如何放置点有了想法 我的问题是如何在程

我做了一个程序,用数值方法求解一组微分方程,描述了一种“任意”疾病如何在一个孤立的、恒定的人群中运动,这是我前一段时间上的一门课的编程作业。我所做的扩展是添加一些可以暂停、重置和“播放”模拟的图形组件,以及一些允许我更改方程式中某些常量的组件

所有这些都是编程方面的练习,因为我觉得它很有趣、令人兴奋,并且希望变得更好

然而,目前我陷入困境,我现在想做的是制作一个非常简单的动画形式。我想将网格中感染者、易感者和抵抗者数量的数据可视化为点。我设法创建了网格,并对如何放置点有了想法

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

我想通过一些关于
paintComponent()
方法的帮助/提示,以及我是否需要使用repaint()方法,我将能够解决这个问题,因为某些原因,我无法解决这些问题。我已经阅读了有关Java的课程文献,但尽管他在大量章节中解释了大多数不同的图形组件,但他并没有对这些方法说太多,只是没有调用
paintComponent()
方法,而是自动完成的

如果有不清楚的地方,请告诉我,我会尽力澄清

提前谢谢

// 福克斯·穆德

我想通过一些关于
paintComponent()
方法的帮助/提示,以及我是否需要使用
repaint()
方法,我将能够解决这个问题,因为某种原因,我无法理解这些问题

基本上,假设您通过扩展
JPanel
来创建自定义组件。当您
@重写
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),以查看图形中的任何更改

你可以在网站上看到更多

为了不处理实际的动画,您需要使用
javax.swing.Timer
。你可以在网站上看到更多。这是基本结构

Timer ( int delayInMillis, ActionListener listener )
其中,
delayInMillis
是滴答声(在本例中为动画)和
ActionListener
侦听“滴答声”之间的延迟时间。每勾选一次,调用
ActionListener
actionPerformed
。在那里,您可以放置代码来更新用于动画的任何变量

例如,在
actionPerformed
中更新x和y,然后调用
repaint()

这只是一个简单的例子。但在本例中,您需要设置散点图的动画。因此,您可以做的是创建一个
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
的每个点,都会调用
repaint()
,并且
paintComponent
将有另一个点绘制圆

结局


UDPATE

我刚才重读了你的问题,我想我误解了。如果你想画出所有的点,那么基本上只有一个列表。先画出所有的点。每次勾选,只需删除第一个索引,将所有剩余索引向上提升一个索引,并在末尾添加一个新索引。虽然这是a的实现,所以您可能只想使用它

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);
    }
}
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();
}