问题
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();
}
}
回答1:
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...
回答2:
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();
来源:https://stackoverflow.com/questions/28032421/using-timer-on-a-paint-component