0

I'm trying to reimplement my Traveling Salesman algorithm into a Swing GUI and it seems like I got most of it working so far. However, when I set the generation size to 10 it runs an endless loop until termination.

class MyPanel extends JPanel{

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
           City city = new City(60, 200);
            TourManager.addCity(city);
            City city2 = new City(180, 200);
            TourManager.addCity(city2);
            City city3 = new City(80, 180);
            TourManager.addCity(city3);
            City city4 = new City(140, 180);
            TourManager.addCity(city4);
            City city5 = new City(20, 160);
            TourManager.addCity(city5);
            City city6 = new City(100, 160);
            TourManager.addCity(city6);
            City city7 = new City(200, 160);
            TourManager.addCity(city7);
            City city8 = new City(140, 140);
            TourManager.addCity(city8);
            City city9 = new City(40, 120);
            TourManager.addCity(city9);
            City city10 = new City(100, 120);
            TourManager.addCity(city10);
            Population population = new Population(50, true);
            for(int i = 0; i<10; i++){
                for(int x2 = 0; x2<9;x2++){
                    City tempCity = population.getFittest().getCity(x2);
                    City tempCity2 = population.getFittest().getCity(x2+1);
                    g2.setStroke(new BasicStroke(3));
                    g2.fillOval(tempCity.getX(), tempCity.getY(), 10, 10);
                    g2.drawLine(tempCity.getX(),tempCity.getY() , tempCity2.getX(), tempCity2.getY());
                }
                population = GA.evolvePopulation(population);
                repaint();
                System.out.println(population.getFittest().getFitness());
            }

    }
}

Update2!:

class MyPanel2 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>();
  Timer timer = new Timer(1000, this);


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

    }

}

  • dont it call paintComponent whenever you call repaint(); closing the endless loop? – Solano Jan 19 '15 at 16:27
  • Sorry, could you reiterate your answer. – monsterbasher Jan 19 '15 at 16:29
  • As per described here [http://stackoverflow.com/questions/16875572/paint-repaint-paintcomponent] when you call repaint() it will call paintComponent. So in your case you will get in a endless loop – Solano Jan 19 '15 at 16:31
  • 1
    Try to put your logic of creating the citizens and the population out of the paintComponent ... of course you will keep the repaint to call the paintComponent only to draw your current iteration – Solano Jan 19 '15 at 16:32
  • So where should I put repaint() so I can see the population evolve dynamically? – monsterbasher Jan 19 '15 at 16:33
  • Try to check my answer below – Solano Jan 19 '15 at 16:41
  • @Solano, no calling `repaint()` actually will not cause endless loop, it simply put a request to paint the component (it is not a synchronous request) – Pham Trung Jan 19 '15 at 16:46
  • @PhamTrung just quoted the link above [http://stackoverflow.com/questions/16875572/paint-repaint-paintcomponent%5D] – Solano Jan 19 '15 at 16:54
  • @Solano, please refer to this: [repaint() merely requests the AWT thread to call update(). It then returns immediately. This type of behaviour is called asynchronous](http://www.scs.ryerson.ca/~mes/courses/cps530/programs/threads/Repaint/index.html) or more [precise, Oracle documentation](http://www.oracle.com/technetwork/java/painting-140037.html) – Pham Trung Jan 19 '15 at 17:04

1 Answers1

1

As i said i tried to separate the logic from the paint. My solution is very bad but can give some feelings.

My idea is: Share the variables that you will use to draw between the Logic method and the Draw method. So you can call the repaint method whenever you want and paintComponent will only execute the reading of the shared vars tempCitys

Something like that:

class MyPanel extends JPanel{
    private ArrayList<City> tempCity;
    private ArrayList<City> tempCity2;

    int delay = 5000;   // 5 sec delay.
    int interval = 1000;  // 1 sec interval.
    Timer timer;

    public MyPanel(){
      timer = new Timer();

      timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            doGA();
        }
      }, delay, interval);
    }

    public void doGA(){
            tempCity = new ArrayList<City>();
            tempCity2 = new ArrayList<City>();
            City city = new City(60, 200);
            TourManager.addCity(city);
            City city2 = new City(180, 200);
            TourManager.addCity(city2);
            City city3 = new City(80, 180);
            TourManager.addCity(city3);
            City city4 = new City(140, 180);
            TourManager.addCity(city4);
            City city5 = new City(20, 160);
            TourManager.addCity(city5);
            City city6 = new City(100, 160);
            TourManager.addCity(city6);
            City city7 = new City(200, 160);
            TourManager.addCity(city7);
            City city8 = new City(140, 140);
            TourManager.addCity(city8);
            City city9 = new City(40, 120);
            TourManager.addCity(city9);
            City city10 = new City(100, 120);
            TourManager.addCity(city10);
            Population population = new Population(50, true);
            for(int i = 0; i<10; i++){
                for(int x2 = 0; x2<9;x2++){
                    tempCity.add(population.getFittest().getCity(x2));
                    tempCity2.add(population.getFittest().getCity(x2+1));
                    repaint();
                }
                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 i=0; i<tempCity.size(); i++){ //Assuming tempCity size = tempcity 2 size (worst way ever)
            g2.fillOval(tempCity.get(i).getX(), tempCity.get(i).getY(), 10, 10);
            g2.drawLine(tempCity.get(i).getX(),tempCity.get(i).getY() , tempCity2.get(i).getX(), tempCity2.get(i).getY());
        } 
    }
}
Solano
  • 550
  • 2
  • 9
  • I tried calling the doGA() method in my createAndDrawGui method which handles painting the JFrame, but it doesn't seem to be correct. Any ideas where I should be calling doGA()? – monsterbasher Jan 19 '15 at 16:48
  • try to call the doGA() after you add the JPanel to the window. i dont remembere how to add the jpanel into the window – Solano Jan 19 '15 at 16:52
  • This logic only draws 1 line and one oval representing the city. Any ideas because i'm stumped. – monsterbasher Jan 19 '15 at 17:22
  • Oh sorry! You have to keep all the references to previous draws. So change the tempCity and tempCity2 to an ArrayList of temp city and whenever you call the repaint, you redraw all tempcity and tempcity2 arraylist – Solano Jan 19 '15 at 17:44
  • I adapted my answer to use arraylist now – Solano Jan 19 '15 at 17:48
  • Ok so I changed your code a bit and removed the TempCity all together but kept the general logic. It works, I think. Just need to slow down each repaint down so I can see whats going on. – monsterbasher Jan 19 '15 at 18:21
  • If it helped you a bit please mark as answer. if not then its alright! bye – Solano Jan 19 '15 at 18:29
  • Just one more question, how should I implement the Timer if i'm repainting from doGA method not from the ActionListener? – monsterbasher Jan 19 '15 at 18:37
  • What is the purpose of Timer? you want to call the whole process each 1000 miliseconds? – Solano Jan 19 '15 at 18:51
  • Just want to see each generation every second for demonstration purposes. – monsterbasher Jan 19 '15 at 18:56
  • Editted my answer and put a contructor..check if it helps.. (with this constructor forget about call doGA() externaly – Solano Jan 19 '15 at 18:56
  • Well I do want to use the Swing.timer as it's designed to GUI components opposed to the utility timer. – monsterbasher Jan 19 '15 at 19:17