2016-05-17 35 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

相關問題