Wątki - zegar

Wątek to program sekwencyjny, który może być wykonywany współbieżnie z innymi wątkami.

  • Wykonywany kod umieszczamy w metodzie run()
  • Wątki uruchamiamy wywołując metodę start()
  • Wątki kończą działanie po wyjściu z metody run()

:!: Uwaga - wywołanie run() wykona funkcję, ale nie jako osobny wątek. :!:

Zegar na konsoli - wątek Clock

Zadeklaruj klasę Clock

public class Clock extends Thread{
 
    @Override
    public void run() {
    }
 
    public static void main(String[] args) {
        new Clock().start();
    }
}

Kod wykonywany przez wątek

Następnie w metodzie run()

  • dodaj pętlę nieskończoną
  • w pętli odczytuj i drukuj bieżący czas
   LocalTime time = LocalTime.now();
   System.out.printf("%02d:%02d:%02d\n",
       time.getHour(),
       time.getMinute(),
       time.getSecond());

Usypianie wątku

Prawdopodobnie ten sam czas drukuje się wielokrotnie. Uśpij wątek na jedną sekundę (1000 milisekund) wprowadzając wywołanie metody sleep()

Zegar z GUI

Zaimplementujemy zegar analogowy wyświetlający (i przesuwający wskazówki).

  • Zegar będzie rysowany wewnątrz klasy ClockWithGui dziedziczącej po JPanel.
  • W funkcji main() utworzona zostanie ramka, dodany do niej panel, itd
public class ClockWithGui extends JPanel {
 
    LocalTime time = LocalTime.now();
 
    public static void main(String[] args) {
        JFrame frame = new JFrame("Clock");
        frame.setContentPane(new ClockWithGui());
        frame.setSize(700, 700);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(true);
        frame.setVisible(true);
 
    }
}

Rysujemy tarczę

Kod umieszczamy w paintComponent()

Poniżej przykład rysowania cyfr na tarczy.

  • definiujemy obrót o wielokrotność 360/12 stopni
  • wyznaczamy obraz punktu w przekształceniu.
  • Ten punkt ma współrzędne (0,-120). Wartość 120 to promień, znak minus bo współrzędne y rosną w dół. Lokalizacja cyfr nie jest idealna, warto odjąć od x (przed przekształceniem) szerokość tekstu. Jeszcze lepiej zrealizowana metoda powinna odczytać wymiary tekstu dla danej czcionki.
   public void paintComponent(Graphics g){
        Graphics2D g2d=(Graphics2D)g;
        g2d.translate(getWidth()/2,getHeight()/2);
 
        for(int i=1;i<13;i++){
            AffineTransform at = new AffineTransform();
            at.rotate(2*Math.PI/12*i);
            Point2D src = new Point2D.Float(0,-120);
            Point2D trg = new Point2D.Float();
            at.transform(src,trg);
            g2d.drawString(Integer.toString(i),(int)trg.getX(),(int)trg.getY());
        }
 
   }

:!: Gdyby ktoś potrzebował inspiracji - można zajrzeć na kod rysujący tarczę zegara w JavaScript. Kontekst graficzny ctx w JavaScript jest analogiem Grapics2D w bibliotece Swing. Transformacje afiniczne mają podobną postać…

Rysujemy wskazówki

Tak możemy narysować jedną ze wskazówek (godzinową)…

Ale popraw poniższy kod, ponieważ położenie wskazówek na ogół nie zmienia się skokowo np. przy zmianie z 11:59:59 na 12:00:00.

        AffineTransform saveAT = g2d.getTransform();
        g2d.rotate(time.getHour()%12*2*Math.PI/12);
        g2d.drawLine(0,0,0,-100);
        g2d.setTransform(saveAT);

Możesz zmienić kształt (np. narysować wielobok) lub użyć pogrubienia g2d.setStroke(new BasicStroke(???, CAP_ROUND,JOIN_MITER))

Kreski na tarczy

Dorysuj samodzielnie…

Animacja wskazówek

W klasie ClockWithGui zadeklaruj klasę wewnętrzną będącą wątkiem.

    class ClockThread extends Thread{
        @Override
        public void run() {
            for(;;){
                time = LocalTime.now();
                System.out.printf("%02d:%02d:%02d\n",time.getHour(),time.getMinute(),time.getSecond());
 
                //sleep(1000);
                repaint();
            }
        }
    }
  • Dlaczego w ClockThread możliwy jest dostęp do atrybutu time?
  • Za co odpowiada metoda repaint()? Jest to metoda wątku czy JPanel?
pz1/watki-zegar.txt · Last modified: 2024/12/16 02:36 by pszwed
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0