在 Paint 组件上使用计时器

Using Timer on a Paint Component

我正在尝试使用遗传算法直观地表示旅行商问题。我想我已经了解了大部分内容,但我需要放慢 repaint() 的速度,这样我才能看到每次迭代发生了什么。知道我应该如何在保留 doGA() 逻辑的同时实现 actionPerformed() 方法吗?

 class MyPanel extends JPanel implements ActionListener{

  private final static int POINTWIDTH = 8;
  private final static Color POINTCOLOR = Color.RED;
  private final static Color LINECOLOR = Color.GREEN;
  private JLabel label =  new JLabel();
  private City city,city2,city3,city4,city5,city6,city7,city8,city9,city10,city11,city12,city13,city14,city15,city16,city17,city18,city19,city20;
  private Population population;
  private ArrayList tempCity = new ArrayList<City>();
  private ArrayList tempCity2 = new ArrayList<City>();

  int delay = 5000;

  Timer timer = new Timer(delay, this);


  public void start(){
      timer.start();

  }

  public void doGA(){
           city = new City(60, 200);
          TourManager.addCity(city);
          city2 = new City(180, 200);
          TourManager.addCity(city2);
         city3 = new City(80, 180);
          TourManager.addCity(city3);
          city4 = new City(140, 180);
          TourManager.addCity(city4);
           city5 = new City(20, 160);
          TourManager.addCity(city5);
          city6 = new City(100, 160);
          TourManager.addCity(city6);
          city7 = new City(200, 160);
          TourManager.addCity(city7);
          city8 = new City(140, 140);
          TourManager.addCity(city8);
          city9 = new City(40, 120);
          TourManager.addCity(city9);
          city10 = new City(100, 120);
          TourManager.addCity(city10);
           city11 = new City(180, 100);
          TourManager.addCity(city11);
           city12 = new City(60, 80);
          TourManager.addCity(city12);
          city13 = new City(120, 80);
          TourManager.addCity(city13);
          city14 = new City(180, 60);
          TourManager.addCity(city14);
           city15 = new City(20, 40);
          TourManager.addCity(city15);
           city16 = new City(100, 40);
          TourManager.addCity(city16);
           city17 = new City(200, 40);
          TourManager.addCity(city17);
           city18 = new City(20, 20);
          TourManager.addCity(city18);
           city19 = new City(60, 20);
          TourManager.addCity(city19);
          city20 = new City(160, 20);
          TourManager.addCity(city20);
          population = new Population(50, true);

                for (int i = 0; i < 100; i++) {

                    population = GA.evolvePopulation(population);
                    repaint();
                    System.out.println(population.getFittest().getFitness());
                }

    }

    public void paintComponent(Graphics g){
         super.paintComponent(g);
          Graphics2D g2 = (Graphics2D) g;
          g2.setStroke(new BasicStroke(3));
          for(int x = 0; x<19;x++){
              g2.setColor(LINECOLOR);
              //g2.drawLine(tempCity.get(x).getX(), tempCity.get(x).getY(), tempCity2.get(x).getX(), tempCity2.get(x).getY());
              g2.drawLine(population.getFittest().getCity(x).getX(), population.getFittest().getCity(x).getY(), population.getFittest().getCity(x+1).getX(), population.getFittest().getCity(x+1).getY());
              g2.setColor(POINTCOLOR);
              g2.fillOval(population.getFittest().getCity(x).getX() - POINTWIDTH/2, population.getFittest().getCity(x).getY() - POINTWIDTH/2, POINTWIDTH, POINTWIDTH);


          }
          g2.setColor(LINECOLOR);
          g2.drawLine(population.getFittest().getCity(19).getX(), population.getFittest().getCity(19).getY(), population.getFittest().getCity(0).getX(), population.getFittest().getCity(0).getY());
          g2.setColor(POINTCOLOR);
          g2.fillOval(population.getFittest().getCity(0).getX() - POINTWIDTH/2, population.getFittest().getCity(0).getY() - POINTWIDTH/2, POINTWIDTH, POINTWIDTH);

    }

    public void actionPerformed(ActionEvent e){
        doGA();

    }

}

如果您的 objective 要致电:

population = GA.evolvePopulation(population);
repaint();
System.out.println(population.getFittest().getFitness());

每秒,例如,您可以使用一个线程:

int i = 0;

Thread thread = new Thread()
{
    public void run()
    {
      if i != 100
      {
        Thread.sleep(1000);                 //1000 milliseconds is one second.
        System.out.println("Thread Running iteration:" + i );
        i++;
        population = GA.evolvePopulation(population);
        SwingUtilities.invokeLater(new Runnable() 
        {
          public void run() 
          {
              // Here, we can safely update the GUI
              // because we'll be called from the
              // event dispatch thread
              repaint();
          }
        });


        System.out.println(population.getFittest().getFitness());


      }
      else
      {
        Thread.currentthread.interrupt()
      }
    }
}

thread.start();

您也可以使用 timer,正如评论中提到的那样:

int delay = 1000; //milliseconds
  ActionListener taskPerformer = new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
          //...Perform a task...
      }
  };
  new Timer(delay, taskPerformer).start();

基本上,Timer 变成了你 for-loop,所以每次它滴答作响时,你都需要增加它的迭代并在绘制之前更新模型的状态。

这意味着您必须将代码的初始化和更新阶段分开,例如...

class MyPanel extends JPanel implements ActionListener{

    private final static int POINTWIDTH = 8;
    private final static Color POINTCOLOR = Color.RED;
    private final static Color LINECOLOR = Color.GREEN;
    private JLabel label =  new JLabel();
    private City city,city2,city3,city4,city5,city6,city7,city8,city9,city10,city11,city12,city13,city14,city15,city16,city17,city18,city19,city20;
    private Population population;
    private ArrayList tempCity = new ArrayList<City>();
    private ArrayList tempCity2 = new ArrayList<City>();

    int delay = 5000;
    private int iteration = 0;

    Timer timer = new Timer(delay, this);


    public void start(){
        iteration = 0;
        timer.start();
    }

    public void initGA() {
        city = new City(60, 200);
        TourManager.addCity(city);
        city2 = new City(180, 200);
        TourManager.addCity(city2);
        city3 = new City(80, 180);
        TourManager.addCity(city3);
        city4 = new City(140, 180);
        TourManager.addCity(city4);
        city5 = new City(20, 160);
        TourManager.addCity(city5);
        city6 = new City(100, 160);
        TourManager.addCity(city6);
        city7 = new City(200, 160);
        TourManager.addCity(city7);
        city8 = new City(140, 140);
        TourManager.addCity(city8);
        city9 = new City(40, 120);
        TourManager.addCity(city9);
        city10 = new City(100, 120);
        TourManager.addCity(city10);
        city11 = new City(180, 100);
        TourManager.addCity(city11);
        city12 = new City(60, 80);
        TourManager.addCity(city12);
        city13 = new City(120, 80);
        TourManager.addCity(city13);
        city14 = new City(180, 60);
        TourManager.addCity(city14);
        city15 = new City(20, 40);
        TourManager.addCity(city15);
        city16 = new City(100, 40);
        TourManager.addCity(city16);
        city17 = new City(200, 40);
        TourManager.addCity(city17);
        city18 = new City(20, 20);
        TourManager.addCity(city18);
        city19 = new City(60, 20);
        TourManager.addCity(city19);
        city20 = new City(160, 20);
        TourManager.addCity(city20);
        population = new Population(50, true);
    }

    public void doGA(){
        population = GA.evolvePopulation(population);
        repaint();
        System.out.println(population.getFittest().getFitness());
    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setStroke(new BasicStroke(3));
        for(int x = 0; x<19;x++){
            g2.setColor(LINECOLOR);
            //g2.drawLine(tempCity.get(x).getX(), tempCity.get(x).getY(), tempCity2.get(x).getX(), tempCity2.get(x).getY());
            g2.drawLine(population.getFittest().getCity(x).getX(), population.getFittest().getCity(x).getY(), population.getFittest().getCity(x+1).getX(), population.getFittest().getCity(x+1).getY());
            g2.setColor(POINTCOLOR);
            g2.fillOval(population.getFittest().getCity(x).getX() - POINTWIDTH/2, population.getFittest().getCity(x).getY() - POINTWIDTH/2, POINTWIDTH, POINTWIDTH);

        }
        g2.setColor(LINECOLOR);
        g2.drawLine(population.getFittest().getCity(19).getX(), population.getFittest().getCity(19).getY(), population.getFittest().getCity(0).getX(), population.getFittest().getCity(0).getY());
        g2.setColor(POINTCOLOR);
        g2.fillOval(population.getFittest().getCity(0).getX() - POINTWIDTH/2, population.getFittest().getCity(0).getY() - POINTWIDTH/2, POINTWIDTH, POINTWIDTH);

    }

    public void actionPerformed(ActionEvent e){
        iteration++;
        if (iteration < 100) {
            doGA();
        } else {
            ((Timer)e.getSource()).stop();
        }
    }
}

简短的回答是,不,你不能保持你的 doGA 方法不变,它必须改变,没有其他方法可以实现它,但更长的答案是,如果您只是将 Timer 视为一种奇特的循环类型,那并不难...