【问题标题】:Java Swing running multiple simulations in a loopJava Swing 在一个循环中运行多个模拟
【发布时间】:2016-05-17 17:48:59
【问题描述】:

我编写了一个简单的模拟程序,其中 2 个以不同速度移动的球尝试移动到帧的中间,然后返回到它们的起始位置。在指定的末尾,totalTime,我结束模拟并记录此数据。

我的问题是,是否可以自动循环并运行多个模拟?目前,当我的totalTime 启动时,动画只是冻结但窗口没有关闭。理想情况下,我想,我希望看到旧窗口关闭,然后弹出一个新窗口,显示不同球的新速度。

所以我的代码看起来像这样:

 public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            double rSpeed = 0;
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
            frame.setSize(500, 500);
            Rectangle r = frame.getBounds();
            frame.add(new MoveAgents(r.getWidth(), rSpeed));
        }            
    });
}

public MoveAgents(double w, double rFrameSpeed) {
     //initialize my 2 balls and their speeds and starting locations

    Timer timer = new Timer(15, null);
    timer.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            totalTime++;

            if (totalTime == 1000) {
                timer.stop();

                try {
                    generateCsvFile(OUTPUT_FILE);
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
          //otherwise, do things 
    }
 }

【问题讨论】:

    标签: java swing


    【解决方案1】:

    是否可以自动循环并运行多个模拟?

    是的。当模拟结束时,不要尝试替换视图。相反,

    • Timer 上调用stop()

    • 调用generateCsvFile() 保存结果。

    • 完全按照第一次的方式初始化模拟模型。

    • Timer 上调用restart()

    在下面的示例中,模型是一个名为 dataint,模拟只是将其渲染并递增到 1000。重复模拟次数的count 作为参数传递给Simulation 构造函数。而不是frame.setSize(),覆盖绘图面板的getPreferredSize(),如here所讨论的那样。

    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    
    /**
     * @see https://stackoverflow.com/a/37293513/230513
     */
    public class SimTest {
    
        private void display() {
            JFrame f = new JFrame("SimTest");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.add(new Simulation(8));
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        }
    
        private static class Simulation extends JPanel {
    
            private final Font font = this.getFont().deriveFont(36f);
            private int count;
            private int data;
            Timer t = new Timer(100, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    repaint();
                    if ((data += 100) == 1000) {
                        t.stop();
                        System.out.println("Saving results…");//generateCsvFile();
                        if (--count == 0) {
                            System.out.println("Fin!");
                            System.exit(0);
                        } else {
                            init();
                            t.restart();
                        }
                    }
                }
            });
    
            public Simulation(int count) {
                this.count = count;
                init();
                t.start();
            }
    
            private void init() {
                data = 0;
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.setFont(font);
                g.drawString(String.valueOf(data), 8, g.getFontMetrics().getHeight());
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(256, 128);
            }
        }
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new SimTest()::display);
        }
    }
    

    【讨论】:

    • 啊,太感谢了!这比我在 main 方法中尝试执行循环时遇到的所有问题要好得多。
    • @Kevin:我发现将javax.swing.Timer 视为提供可以从外部控制且不会阻塞EDT 的循环很有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-11
    • 2021-01-14
    • 2022-11-23
    • 1970-01-01
    • 2021-06-11
    • 1970-01-01
    • 2021-03-30
    相关资源
    最近更新 更多