Sunday, March 20, 2016

Analoge Uhr in Java

Analoge Uhr in Java


Wie programmiert man eigentlich eine analoge Uhr?
Ist eigentlich nicht so schwierig, jedoch braucht man dazu ein bisschen Trigonometrie und ein Verständnis von Thread. Das ergebnis dieses kleinen Tutorials sieht folgendermassen aus;



Wir werden dazu keine Engine,Library oder so was in der art verwenden. Wir überschreiben lediglich die Paint methode des Frames und zeichnen ganz normale Java Lines mit dem Graphic object. Dazu habe ich ein Modell erstellt mit dem Namen Clock, dieses gibt uns pro Sekunde die verschiedenen Coordinaten zum zeichnen, welche es berechnet hat.
Man muss also eine Formel haben die von Sekunden, Minuten und Stunden auf die Coordinaten der Zeiger kommt. Diese sieht wie folgt aus:
    private void calculateCorrs(){
        this.Sec = new Date().getSeconds();
        this.Minute = new Date().getMinutes();
        this.Hour = new Date().getHours();
        int xsecond = (int) (Math.cos(Sec * 3.14f / 30 - 3.14f / 2) * 120 + ORIGIN.x); 
        int ysecond = (int) (Math.sin(Sec * 3.14f / 30 - 3.14f / 2) * 120 + ORIGIN.y);
        this.secCorr = new Point(xsecond,ysecond);
        int xminute = (int) (Math.cos(Minute * 3.14f / 30 - 3.14f / 2) * 100 + ORIGIN.x); 
        int yminute = (int) (Math.sin(Minute * 3.14f / 30 - 3.14f / 2) * 100 + ORIGIN.y); 
        int xhour = (int) (Math.cos((Hour * 30 + Minute / 2) * 3.14f / 180 - 3.14f / 2) * 80 + ORIGIN.x); 
        int yhour = (int) (Math.sin((Hour * 30 + Minute / 2) * 3.14f / 180 - 3.14f / 2) * 80 + ORIGIN.y);
        this.minCorr = new Point(xminute,yminute);
        this.hourCorr = new Point(xhour,yhour);
    }




Der Punkt Origin ist der Punkt welche alle drei Zeiger gemeinsam haben. Nähmlich die Mitte unserer Uhr. In diesem Fall hat das Frame eine Grösse von 350 auf 350 und der Origin ist somit 175,175.

Jetzt noch die update und Paint Methode und das ganze sollte ziehmlich klar werden.

Update:
    @Override
    public void update(Observable o, Object arg) {
        zeichne = true;
        Clock c = (Clock)o;
        this.secCorr = c.getSecCorr();
        this.minCorr = c.getMinCorr();
        this.hourCorr = c.getHourCorr();
        this.repaint();
        this.revalidate();
    }


Paint:
@Override
    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2 = (Graphics2D) g;
        if(zeichne){
            RenderingHints rh = new RenderingHints(this.renderHints);
            g2.setRenderingHints(rh);
            g2.setColor(Color.BLACK);
            g2.setColor(Color.red);
            g2.drawLine(Center.x, Center.y, secCorr.x, secCorr.y);
            g2.setColor(Color.WHITE);
            g2.drawLine(Center.x, Center.y, minCorr.x,minCorr.y);
            g2.drawLine(Center.x, Center.y, hourCorr.x, hourCorr.y);
            g2.drawLine(175,25,175,40);
            g2.drawLine(175, 335, 175, 350);
            g2.drawLine(0, 175, 15, 175);
            g2.drawLine(335, 175, 350, 175);
            g2.drawString("12",168,55);
            g2.drawString("3", 325,180);
            g2.drawString("6", 172,325);
            g2.drawString("9",20,180);
        }
    }



Die Striche von 6,12,3,9 sind hardcoded. Das ist in unserem Fall nicht problematisch, da das Fenster nicht resizeble ist.

Der weitere Code erklärt sich von selbst, diesen kann man unter meinem Github Profil finden.
Das Repo : https://github.com/marcin96/AnalogClock.git

No comments:

Post a Comment