2016-05-17 69 views
1

我已经编码了一个简单的模拟,其中2个以不同速度移动的球试图移动到框架的中间,然后移回到它们的起始位置。在最后指定的totalTime,我结束了模拟并记录了这些数据。Java Swing在一个循环中运行多个模拟

我的问题是,是否有可能循环并自动运行多个模拟?目前,当我的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 
    } 
} 

回答

2

是否可以遍历并自动运行多个模拟?

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

  • Timer调用stop()

  • 调用generateCsvFile()来保存结果。

  • 初始化模拟模型与第一次完全相同。

  • Timer上调用restart()

在下面的例子中,模型是一个int命名data,其模拟只是呈现和增量1000。将重复模拟次数的count作为参数传递给构造函数Simulation。代替frame.setSize(),覆盖绘图面板的getPreferredSize(),如here所述。

image

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); 
    } 
} 
+0

啊谢谢太神奇了!这比我在主要方法中尝试执行循环时遇到的所有问题都要好得多。 – Kevin

+0

@Kevin:我觉得把'javax.swing.Timer'看作提供一个可以外部控制并且不会阻止[EDT]的循环是有帮助的(http://docs.oracle.com/javase/tutorial /uiswing/concurrency/initial.html)。 – trashgod