Using Timer on a Paint Component

2019-09-20 15:46发布

I'm trying to make a visual representation of the traveling salesman problem using a genetic algorithm. I think I got most of it down but I need to slow the repaint() so i can see what's happening each iteration. Any idea how I should implement the actionPerformed() method while retaining the doGA() logic?

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

    }

}

2条回答
再贱就再见
2楼-- · 2019-09-20 16:22

IF your objective is to call :

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

every seconds, as example, you could use a thread:

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

You could also use a timer, as someone mentionned in the comments:

int delay = 1000; //milliseconds
  ActionListener taskPerformer = new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
          //...Perform a task...
      }
  };
  new Timer(delay, taskPerformer).start();
查看更多
萌系小妹纸
3楼-- · 2019-09-20 16:31

Basically, the Timer becomes you for-loop, so each time it ticks, you need to increment it's iteration and update the state of the model before it's painted.

This means you will HAVE to separate the initialisation and update phases of your code, for example...

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

The short answer would be, no, you can't keep your doGA method as it is, it must be changed, there simply is no other way to achieve it, but the longer answer is, it's not that hard if you simply think of the Timer as a fancy type of loop...

查看更多
登录 后发表回答