# Timer programmieren



## didi577 (15. Mrz 2017)

Hallo,

ich möchte einen Timer programmieren. Die Zeit soll im Format mm:ss angezeigt werden. Zur Einstellung soll mit Klick auf einen JButton(+) mm um eins (eine Minute) erhöht werden. Mit Klick auf einen JButton(start) soll die Uhr rückwärts laufen, sprich mm:ss sollen auf null runter gezählt werden. Den GUI Kram bekomme ich hin. Mir fehlt der richtige Ansatz für den Timer. Kann mir jemand einen heissen Tipp geben wie ich den Timer am besten programmieren kann?


----------



## Thallius (15. Mrz 2017)

Kommt auf das UI an. Bei Swing würde ich zu einem Swingworker greifen


----------



## didi577 (15. Mrz 2017)

hab hier mal meinen Code. im Prinzip funktioniert der Timer schon einwandfrei, nur die Anzeige der Sekunden 60, 120 etc. soll durch mm:ss ersetzt werden..

```
public class Wecker extends JFrame {

   private static final long serialVersionUID = 1L;
   public static int minClicks = 0;
   public static Timer timer;
   private JButton plus, minus, start, reset;
   JLabel zeit;

   public Wecker() {

       bauen();
       addButton();
       methoden();
       
   }

   public void bauen() {

       ImageIcon imageIcon = new ImageIcon("d:/eclipse/workspace/Timer/src/TimerO/timer.png");
       this.setIconImage(imageIcon.getImage());
       this.setSize(280, 230);
       this.setLocationRelativeTo(null);
       this.setTitle("It's teatime 1.0");
       this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       this.setAlwaysOnTop(false);
       this.setFocusable(true);
       this.requestFocus();
       
       plus = new JButton("+");
       plus.setFont(new Font("Verdana", Font.BOLD, 18));
       plus.addActionListener(new plusAction());
       minus = new JButton("-");
       minus.setFont(new Font("Verdana", Font.BOLD, 24));
       minus.addActionListener(new minusAction());
       start = new JButton("Start");
       start.setFont(new Font("Verdana", Font.BOLD, 14));
       start.addActionListener(new startAction());
       reset = new JButton("Reset");
       reset.setFont(new Font("Verdana", Font.BOLD, 14));
       reset.addActionListener(new resetAction());
       zeit = new JLabel("0");
       zeit.setHorizontalAlignment(JLabel.CENTER);
       zeit.setFont(new Font("Verdana", Font.PLAIN, 42));
       zeit.setOpaque(true);
       zeit.setBackground(null);
   }

   public void addButton() {

       getContentPane().add(start, BorderLayout.PAGE_START);
       getContentPane().add(plus, BorderLayout.LINE_START);
       getContentPane().add(minus, BorderLayout.LINE_END);
       getContentPane().add(reset, BorderLayout.PAGE_END);
       getContentPane().add(zeit, BorderLayout.CENTER);
   }

   private class plusAction implements ActionListener {
       public void actionPerformed(ActionEvent e) {
           minClicks += 60;
           zeit.setText("" + minClicks);
           if (minClicks > 0) {
               start.setBackground(Color.green);
           }
       }
   };

   private class minusAction implements ActionListener {
       public void actionPerformed(ActionEvent e) {
           if (minClicks >= 1) {
               minClicks -= 60;
           }
           if (minClicks == 0) {
               start.setBackground(null);
           }
           zeit.setText("" + minClicks);
       }
   };

   private class resetAction implements ActionListener {
       public void actionPerformed(ActionEvent e) {
           Wecker.timer.stop();
           minus.setEnabled(true);
           minClicks = 0;
           start.setBackground(null);
           zeit.setText("" + minClicks);

       }
   };

   private class startAction implements ActionListener {
       public void actionPerformed(ActionEvent e) {
           if (minClicks > 0) {
               timer.start();
               minus.setEnabled(false);
               java.awt.Toolkit.getDefaultToolkit().beep();
           }


       }

   };

   public void methoden() {

       // Tastatursteuerung
       this.addKeyListener(new KeyListener() {

           @Override
           public void keyTyped(KeyEvent e) {

           }

           @Override
           public void keyReleased(KeyEvent e) {

           }

           @Override
           public void keyPressed(KeyEvent e) {

               if (e.getKeyCode() == KeyEvent.VK_ADD)
                   minClicks += 60;
               zeit.setText("" + minClicks);
               if (minClicks > 0) {
                   start.setBackground(Color.green);
               }
               if (e.getKeyCode() == KeyEvent.VK_SUBTRACT)
                   if (minClicks >= 1) {
                       minClicks -= 60;
                   }
               if (minClicks == 0) {
                   start.setBackground(null);
               }
               if (e.getKeyCode() == KeyEvent.VK_ENTER)
                   if (minClicks > 0) {
                       timer.start();
                       minus.setEnabled(false);
                       java.awt.Toolkit.getDefaultToolkit().beep();
                   }
           }
       });

       Wecker.timer = new Timer(1000, new ActionListener() {
           public void actionPerformed(ActionEvent e) {
               Wecker.minClicks--;
               zeit.setText("" + minClicks);
               if (minClicks == 10) { // Fenster ist die letzten 10
                   setAlwaysOnTop(true); // sec. immer im Vordergrund
               }
               if (minClicks == 5) {
                   java.awt.Toolkit.getDefaultToolkit().beep();
               }
               if (minClicks == 4) {
                   java.awt.Toolkit.getDefaultToolkit().beep();
               }
               if (minClicks == 3) {
                   java.awt.Toolkit.getDefaultToolkit().beep();
               }
               if (minClicks == 2) {
                   java.awt.Toolkit.getDefaultToolkit().beep();
               }
               if (minClicks == 1) {
                   java.awt.Toolkit.getDefaultToolkit().beep();
               }
               if (minClicks == 0) {
                   Wecker.timer.stop();
                   start.setBackground(null);
                   minus.setEnabled(true);
                   java.awt.Toolkit.getDefaultToolkit().beep(); 

               }

           }
       });

   }
}

public class WeckerProgramm {
   
   public static void main(String[] args) {
       
       try {

           UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
       } catch (Exception e) {
           e.printStackTrace();
       }
       
       JFrame frame = new Wecker();
       frame.setVisible(true);
       
   }
   
}
```
bekomme ich das in diesem Rahmen hin?


----------



## Joose (15. Mrz 2017)

Klar ist sogar ganz einfach: Schreib dir einfach eine Methode welche die einen Integer entgegennimmt.
Dieser wird dann in die entsprechenden Zeitstring umgewandelt und gibt diesen zurück.


```
Wecker.timer = new Timer(1000, new ActionListener() {
   public void actionPerformed(ActionEvent e) {
       Wecker.minClicks--;
       zeit.setText(formatToTime(minClicks));
       if (minClicks == 10) { // Fenster ist die letzten 10
           setAlwaysOnTop(true); // sec. immer im Vordergrund
       } else if (minClicks <= 5) {
           if (minClicks == 0) {
               Wecker.timer.stop();
               start.setBackground(null);
               minus.setEnabled(true);
           }
           java.awt.Toolkit.getDefaultToolkit().beep();
       }
   }
});
```

PS: hab dir deine if vereinfacht


----------



## didi577 (15. Mrz 2017)

ok vielen Dank, ich werde es probieren


----------



## mrBrown (15. Mrz 2017)

Thallius hat gesagt.:


> Kommt auf das UI an. Bei Swing würde ich zu einem Swingworker greifen


Hat Swingworker da irgendeinen Vorteil gegenüber Timer?


----------



## Thallius (15. Mrz 2017)

mrBrown hat gesagt.:


> Hat Swingworker da irgendeinen Vorteil gegenüber Timer?



Naja ich kann halt direkt mit publish() das UI aktualisieren und muss nicht irgendwelche Umwege über SwingUtilities.invokeLater() o.ä. gehen.


----------



## mrBrown (15. Mrz 2017)

Thallius hat gesagt.:


> Naja ich kann halt direkt mit publish() das UI aktualisieren und muss nicht irgendwelche Umwege über SwingUtilities.invokeLater() o.ä. gehen.


javax.swing.Timer läuft auch im passenden Thread, ist ja hier auch so umgesetzt


----------



## didi577 (16. Mrz 2017)

@Joose 


Joose hat gesagt.:


> Schreib dir einfach eine Methode welche die einen Integer entgegennimmt.
> Dieser wird dann in die entsprechenden Zeitstring umgewandelt und gibt diesen zurück.


ich probiere hier etwas herum

```
public void umwandeln() {
       
       Integer integer = new Integer(minClicks);
       
   }
```

die Methode würde ich so beginnen...
du hast in dem berichtigten Code bereits die Zeile:

```
zeit.setText(formatToTime(minClicks));
```
 eingefügt
ich komme nicht weiter, muss ich erst ein Date Objekt erzeugen um die mm:ss zu bekommen?


----------



## Joose (16. Mrz 2017)

didi577 hat gesagt.:


> ```
> public void umwandeln() {
> Integer integer = new Integer(minClicks);
> }
> ...


Warum? "minClicks" ist doch schon ein int warum also ein Integer erzeugen? Welchen Vorteil erhoffst du dir davon?



didi577 hat gesagt.:


> du hast in dem berichtigten Code bereits die Zeile:
> 
> ```
> zeit.setText(formatToTime(minClicks));
> ...


Nein musst du nicht. Du hast die Variable "minClicks" welche die noch abzuzählende Sekunden enthält.
Du musst dir davon die Minuten ausrechnen und die restlichen Sekunden.
1 Minute = 60 Sekunden -> wie oft kommt 60 in minClicks vor?
Wie berechnest du dir dann die restlichen Sekunden?

Diese beiden Werte mit einen ":" dazwischen zusammenhängen und fertig (wobei ein Schönheitsfehler wird dir dann vl auffallen, aber denn solltest du selber lösen können )


----------



## didi577 (16. Mrz 2017)

@Joose 
ich denke ich habs:

```
package TimerO;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.text.DecimalFormat;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;

public class Wecker extends JFrame {

   private static final long serialVersionUID = 1L;
   public static int minClicks = 0;
   public static Timer timer;
   private JButton plus, minus, start, reset;
   JLabel zeit;
   int mm = 0;
   int ss = 0;

   public Wecker() {

       bauen();
       addButton();
       methoden();

   }

   public void bauen() {

       ImageIcon imageIcon = new ImageIcon(
               "d:/eclipse/workspace/Timer/src/TimerO/timer.png");
       this.setIconImage(imageIcon.getImage());
       this.setSize(280, 230);
       this.setLocationRelativeTo(null);
       this.setTitle("It's teatime 1.0");
       this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       this.setAlwaysOnTop(false);
       this.setFocusable(true);
       this.requestFocus();

       plus = new JButton("+");
       plus.setFont(new Font("Verdana", Font.BOLD, 18));
       plus.addActionListener(new plusAction());
       minus = new JButton("-");
       minus.setFont(new Font("Verdana", Font.BOLD, 24));
       minus.addActionListener(new minusAction());
       start = new JButton("Start");
       start.setFont(new Font("Verdana", Font.BOLD, 14));
       start.addActionListener(new startAction());
       reset = new JButton("Reset");
       reset.setFont(new Font("Verdana", Font.BOLD, 14));
       reset.addActionListener(new resetAction());
       zeit = new JLabel("00:00");
       zeit.setHorizontalAlignment(JLabel.CENTER);
       zeit.setFont(new Font("Verdana", Font.PLAIN, 42));
       zeit.setOpaque(true);
       zeit.setBackground(null);
   }

   public void addButton() {

       getContentPane().add(start, BorderLayout.PAGE_START);
       getContentPane().add(plus, BorderLayout.LINE_START);
       getContentPane().add(minus, BorderLayout.LINE_END);
       getContentPane().add(reset, BorderLayout.PAGE_END);
       getContentPane().add(zeit, BorderLayout.CENTER);
   }

   private class plusAction implements ActionListener {
       public void actionPerformed(ActionEvent e) {
           minClicks += 60;
           mm = minClicks / 60;
           DecimalFormat formatter = new DecimalFormat("00");
           String mmFormatted = formatter.format(mm);
           String ssFormatted = formatter.format(ss);
           zeit.setText(mmFormatted + ":" + ssFormatted);
           if (minClicks > 0) {
               start.setBackground(Color.green);

           }
       }
   };

   private class minusAction implements ActionListener {
       public void actionPerformed(ActionEvent e) {
           if (minClicks >= 1) {
               minClicks -= 60;
               mm = minClicks / 60;
               DecimalFormat formatter = new DecimalFormat("00");
               String mmFormatted = formatter.format(mm);
               String ssFormatted = formatter.format(ss);
               zeit.setText(mmFormatted + ":" + ssFormatted);
           }
           if (minClicks == 0) {
               start.setBackground(null);
           }

       }
   };

   private class resetAction implements ActionListener {
       public void actionPerformed(ActionEvent e) {
           Wecker.timer.stop();
           minus.setEnabled(true);
           minClicks = 0;
           start.setBackground(null);
           zeit.setText("00:00");

       }
   };

   private class startAction implements ActionListener {
       public void actionPerformed(ActionEvent e) {
           if (minClicks > 0) {
               timer.start();
               minus.setEnabled(false);
           }

       }

   };

   public void methoden() {

       Wecker.timer = new Timer(1000, new ActionListener() {
           public void actionPerformed(ActionEvent e) {
               Wecker.minClicks--;
               mm = minClicks / 60;
               ss = ((60 * mm)-minClicks) *-1;
               DecimalFormat formatter = new DecimalFormat("00");
               String mmFormatted = formatter.format(mm);
               String ssFormatted = formatter.format(ss);
               zeit.setText(mmFormatted + ":" + ssFormatted);
               if (minClicks == 10) {
                   setAlwaysOnTop(true);
               } else if (minClicks <= 5) {
                   if (minClicks == 0) {
                       Wecker.timer.stop();
                       start.setBackground(null);
                       minus.setEnabled(true);
                   }
                   java.awt.Toolkit.getDefaultToolkit().beep();
               }
           }
       });

   }
}
package TimerO;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.UIManager;

public class WeckerProgramm {
   
   public static void main(String[] args) {
       
       try {

           UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
       } catch (Exception e) {
           e.printStackTrace();
       }
       
       JFrame frame = new Wecker();
       frame.setVisible(true);
       
   }
   
}
```
ich weiß nicht ob das die schönste Lösung ist aber der Wecker läuft wie gewünscht


Joose hat gesagt.:


> wobei ein Schönheitsfehler wird dir dann vl auffallen


 hab noch nix gesehen..???


----------



## Joose (16. Mrz 2017)

didi577 hat gesagt.:


> ich weiß nicht ob das die schönste Lösung ist aber der Wecker läuft wie gewünscht


Ich würde das in eine eigene Methode auslagern, du hast die Umformung von minClicks zum Text 3x in der Klasse stehen. 
Nehmen wir an du willst diese Ausgabe anpassen dann musst du das an 3 Stellen machen. Wenn du es in eine Methode auslagerst nur an einer 


```
public static String formatToTime(int minClicks) {
       int minutes = minClicks / 60;
       int seconds = minClicks % 60;
       DecimalFormat formatter = new DecimalFormat("00");
       return formatter.format(minutes) + ":" + formatter.format(seconds);
   }
```
Habe auch die Berechnung für die Sekunden vereinfacht. Das "%" ist der Modulo Operator.



didi577 hat gesagt.:


> hab noch nix gesehen..???


Den hast du schon behoben indem du den DecimalFormatter verwendest


----------



## didi577 (16. Mrz 2017)

ok vielen vielen Dank für deine Hilfe und die Denkanstöße


----------



## Harry Kane (16. Mrz 2017)

Jetzt müssten nur noch die statics und die public Instanzvariablen weg.


----------

