package de.nerdwest.tsp; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.table.DefaultTableModel; import javax.swing.JTabbedPane; import javax.swing.JTextField; import javax.swing.JTable; import java.awt.SystemColor; /** * Das ist die Fenster-Klasse, sie enthaelt die grafischen Anzeige- und Bedienelemente. * @author Prof. Dr. Oliver S. Lazar * @version 1.0 * */ public class TSPFrame extends JFrame implements ActionListener{ private static final long serialVersionUID = 1L; private static final String PREFERRED_LOOK_AND_FEEL = null; private Rundreise rrAktuell, rrInitial; private JTextField anzahl, sigma, sigmaReduktion, abbruch, zeit; private JButton start, stop, init; private SimulatedAnnealing sa; private JTabbedPane tabbedPane; private JTable table; private DefaultTableModel model; /** * Konstruktor */ public TSPFrame() { super("TSP mit Simulated Annealing [1.0] - Prof. Dr. Oliver S. Lazar"); tabbedPane = new JTabbedPane(JTabbedPane.TOP); getContentPane().add(tabbedPane, BorderLayout.CENTER); JPanel panel = new JPanel(); getContentPane().add(panel, BorderLayout.SOUTH); panel.setLayout(new GridLayout(1,2)); JPanel panelLeft = new JPanel(); panelLeft.setLayout(new GridLayout(4,1)); JPanel panel2 = new JPanel(); panel2.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5)); JPanel panel3 = new JPanel(); panel3.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5)); JPanel panel4 = new JPanel(); panel4.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5)); JPanel panel5 = new JPanel(); panel5.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5)); panelLeft.add(panel2); panelLeft.add(panel3); panelLeft.add(panel4); panelLeft.add(panel5); panel.add(panelLeft); JLabel lblAnzahl = new JLabel("Anzahl Staedte:"); panel2.add(lblAnzahl); anzahl = new JTextField(3); anzahl.setText("20"); panel2.add(anzahl); init = new JButton("Generiere Zufallsrundreise"); init.addActionListener(this); panel2.add(init); JLabel lblSigma = new JLabel("Toleranzwert Sigma:"); panel3.add(lblSigma); sigma = new JTextField(5); sigma.setText("10000"); panel3.add(sigma); JLabel lblReduktion = new JLabel("Sigma Reduktion:"); panel3.add(lblReduktion); sigmaReduktion = new JTextField(5); sigmaReduktion.setText("0.005"); panel3.add(sigmaReduktion); panel4.add(new JLabel("Abbruch nach ")); abbruch = new JTextField(3); abbruch.setText("40"); panel4.add(abbruch); panel4.add(new JLabel("stabilen Iterationen (zum Deaktivieren -1)")); zeit = new JTextField(3); zeit.setText("5"); panel5.add(zeit); panel5.add(new JLabel("ms pro Iteration ")); start = new JButton("Rundreise optimieren"); start.addActionListener(this); panel5.add(start); stop = new JButton("Stop"); stop.addActionListener(this); panel5.add(stop); table = new JTable(5,2); table.setBackground(SystemColor.window); table.setRowSelectionAllowed(false); table.setColumnSelectionAllowed(true); table.setCellSelectionEnabled(true); model = (DefaultTableModel)table.getModel(); model.setValueAt("Sigma", 0, 0); model.setValueAt("Iterationen", 1, 0); model.setValueAt("stabile Iterationen", 2, 0); model.setValueAt("Initialdistanz", 3, 0); model.setValueAt("Finaldistanz", 4, 0); table.setEnabled(false); panel.add(table); // Fenstergroesse setzen. setSize (820, 600); // Definieren, was beim Schliessen des Fensters geschehen soll. setDefaultCloseOperation (EXIT_ON_CLOSE); // mittig ausrichten this.setLocationRelativeTo(null); // Fenster anzeigen. setVisible (true); erzeugeRundreise(); } private static void installLnF() { try { String lnfClassname = PREFERRED_LOOK_AND_FEEL; if (lnfClassname == null) lnfClassname = UIManager.getCrossPlatformLookAndFeelClassName(); UIManager.setLookAndFeel(lnfClassname); } catch (Exception e) { System.err.println("Cannot install " + PREFERRED_LOOK_AND_FEEL + " on this platform:" + e.getMessage()); } } /** * Startmethode */ public static void main(String[] args) { installLnF(); SwingUtilities.invokeLater(new Runnable() { public void run() { new TSPFrame(); } }); } public void actionPerformed(ActionEvent e) { if(e.getSource()==init){ erzeugeRundreise(); }else if(e.getSource()==start){ // Ueberpruefe die Eingaben try{ boolean check = true; double sigma = Double.parseDouble(this.sigma.getText()); double sigmaReduktion = Double.parseDouble(this.sigmaReduktion.getText()); double abbruch = Double.parseDouble(this.abbruch.getText()); double zeit = Double.parseDouble(this.zeit.getText()); if(sigma<1){ JOptionPane.showMessageDialog(this, "Sigma: Ungueltiger Wert"); check = false; } if(sigmaReduktion<=0){ JOptionPane.showMessageDialog(this, "Reduktion: Ungueltiger Wert"); check = false; } if(abbruch==0){ JOptionPane.showMessageDialog(this, "Stabile Iterationen: Ungueltiger Wert"); check = false; } if(zeit<0){ JOptionPane.showMessageDialog(this, "Geschwindigkeit: Ungueltiger Wert"); check = false; } if(check){ sa = new SimulatedAnnealing(this, rrAktuell, sigma, sigmaReduktion); sa.start(); } }catch(NumberFormatException ex){ JOptionPane.showMessageDialog(this, "Ungueltiger Wert"); } }else if(e.getSource()==stop){ if(sa!=null && sa.isAlive()){ sa.stopThread(); } } } /** * Erzeugt eine zufällige Rundreise (initiale Route). */ private void erzeugeRundreise(){ try{ boolean check = true; int anzahl = Integer.parseInt(this.anzahl.getText()); if(anzahl<=1){ JOptionPane.showMessageDialog(this, "Anzahl Staedte: Ungueltiger Wert"); check = false; } if(check){ // Rundreise erzeugen rrAktuell = new Rundreise(anzahl); rrInitial = new Rundreise(0); rrInitial.setRundreise(rrAktuell.getRundreise()); tabbedPane.removeAll(); tabbedPane.addTab("Aktuelle Rundreise", null, rrAktuell, "Zeigt die aktuelle Rundreise"); tabbedPane.addTab("Initiale Rundreise", null, rrInitial, "Zeigt die initiale Rundreise"); repaint(); model.setValueAt(rrInitial.getDistanz(), 3, 1); model.setValueAt("", 0, 1); model.setValueAt("", 1, 1); model.setValueAt("", 2, 1); model.setValueAt("", 4, 1); } }catch(NumberFormatException ex){ JOptionPane.showMessageDialog(this, "Anzahl Staedte: Ungueltiger Wert"); } } public JButton getStart() { return start; } public JButton getInit() { return init; } public int getAbbruch(){ return Integer.parseInt(abbruch.getText()); } public int getZeit(){ return Integer.parseInt(zeit.getText()); } /** * Aktualisiert die Tabellenwerte in der GUI * @param sigma Aktueller Toleranzwert * @param iterationen Anzahl Iterationen * @param stabileIterationen Anzahl stabiler Iterationen (ohne Staedtetausch) * @param distanz Die aktuelle Distanz der Rundreise */ public void setTableValues(double sigma, int iterationen, int stabileIterationen, int distanz){ model.setValueAt(sigma, 0, 1); model.setValueAt(iterationen, 1, 1); model.setValueAt(stabileIterationen, 2, 1); model.setValueAt(distanz, 4, 1); } }