Programowanie w języku Delphi » Gotowce

Zegar analogowy

  • 2009-01-09 21:28
  • 7 komentarzy
  • 2301 odsłon
  • Oceń ten tekst jako pierwszy
Poniższy kod rysuje na wybranym Canvasie prosty, analogowy zegarek.

Najpierw w sekcji type wklejamy następujący typ danych:

TClockOptions = packed record
    HourWidth: Integer;
    HourColor: TColor;
    HourStyle: TPenStyle;
    MinuteWidth: Integer;
    MinuteColor: TColor;
    MinuteStyle: TPenStyle;
    SecondWidth: Integer;
    SecondColor: TColor;
    SecondStyle: TPenStyle;
 end;


Procedura rysująca wskazówki, oraz druga, rysująca reszte zegara:
procedure DrawAnalogClock(T: TDateTime; Canvas: TCanvas; R, Left, Top: Integer; Options: TClockOptions);
var
  h, m, s, x, y: Integer;
begin
  h := StrToInt(FormatDateTime('h', T));
  m := StrToInt(FormatDateTime('n', T));
  s := StrToInt(FormatDateTime('s', T));
  Canvas.MoveTo(Left + R, Top + R);
  x := Round(cos(PI * (30 * h + (m / 2) - 90) / 180) * (R - (R / 100 * 30)) + Left + R);
  y := Round(sin(PI * (30 * h + (m / 2) - 90) / 180) * (R - (R / 100 * 30)) + Top + R);
  Canvas.Pen.Width := Options.HourWidth;
  Canvas.Pen.Color := Options.HourColor;
  Canvas.Pen.Style := Options.HourStyle;
  Canvas.LineTo(x, y);
  Canvas.MoveTo(Left + R, Top + R);
  x := Round(cos(PI * (6 * m - 90) / 180) * (R - (R / 100 * 10)) + Left + R);
  y := Round(sin(PI * (6 * m - 90) / 180) * (R - (R / 100 * 10)) + Top + R);
  Canvas.Pen.Width := Options.MinuteWidth;
  Canvas.Pen.Color := Options.MinuteColor;
  Canvas.Pen.Style := Options.MinuteStyle;
  Canvas.LineTo(x, y);
  Canvas.MoveTo(Left + R, Top + R);
  x := Round(cos(PI * (6 * s - 90) / 180) * (R - (R / 100 * 10)) + Left + R);
  y := Round(sin(PI * (6 * s - 90) / 180) * (R - (R / 100 * 10)) + Top + R);
  Canvas.Pen.Width := Options.SecondWidth;
  Canvas.Pen.Color := Options.SecondColor;
  Canvas.Pen.Style := Options.SecondStyle;
  Canvas.LineTo(x, y);
end;
 
procedure DrawClockShield(Canvas: TCanvas; R, Left, Top, Width: Integer; Color: TColor);
var
  x1, y1, x2, y2, i: Integer;
begin
  Canvas.Pen.Width := Width;
  Canvas.Pen.Color := Color;
  i := 0;
  while i < 360 do begin
    x1 := Round(cos(PI * i / 180) * R + Left + R);
    y1 := Round(sin(PI * i / 180) * R + Top + R);
    x2 := Round(cos(PI * i / 180) * (R - (R / 100 * 7)) + Left + R);
    y2 := Round(sin(PI * i / 180) * (R - (R / 100 * 7)) + Top + R);
    Canvas.MoveTo(x1, y1);
    Canvas.LineTo(x2, y2);
    i := i + 30;
  end;
end;


Omówie parametry

Procedura DrawAnalogClock:
T - wybrany przez nas czas (aktualny czas możemy pobrac poprzez funkcje Time)
Canvas - płótno na którym będziemy rysowac
R - promień naszego zegara
Left - pozycja x na canvasie
Top - pozycja y na canvasie
Options - Opcje naszego zegara (takie jak grubośc wskazówek, ich kolor, styl)

Procedura DrawClockShield:
Canvas - płótno na którym będziemy rysowac
R - promień naszego zegara
Left - pozycja x na canvasie
Top - pozycja y na canvasie
Width - grubośc kresek wyznaczających godziny
Color - kolor :]

Przykład użycia:

Na formę dajemy Timera i wpisujemy w zdarzeniu onTimer taki kod:
var
  Options: TClockOptions; // Deklarujemy zmienną z opcjami zegara
begin
  Repaint; // Czyścimy canvas formy
  Options.HourWidth := 2; 
  Options.HourColor := clBlack;
  Options.HourStyle := psSolid; 
  Options.SecondWidth := 1; 
  Options.SecondColor := clRed;
  Options.SecondStyle := psSolid; 
  Options.MinuteWidth := 2;
  Options.MinuteColor := clBlack;
  Options.MinuteStyle := psSolid;
  DrawClockShield(Canvas, 100, 20, 20, 4, clBlack);
  // Rysujemy tarczę zegarową na płótnie formy kolorem czarnym i grubości 4 pikseli. Promień 100 pikseli, pozycja x i y 20 pikseli.
 
  DrawAnalogClock(Time, Canvas, 100, 20, 20, Options); 
  // Rysujemy zegar z aktualnym czasem na płótnie formy. Promień 100 pikseli, pozycja x i y 20 pikseli.
 
  Caption := FormatDateTime('h:nn:ss', Time); // Wyświetlenie czasu w tytule formy
 
end;

7 komentarzy

Elhatron 2012-06-04 16:55

a jak zrobić, żeby nam się to robiło na obiekcie Image , a nie na formie??

darekielb 2009-05-27 13:01

Mam pytanie czy posiada ktoś strukturę do programu ze stoperem analogowym?
Muszę zrobić na zaliczenie, a nie mogę dojść końca z tym programem :/
Jak zrobić żeby stoper zaczynał liczenie od zera, bo tego nie kojarzę

misiu_mietowy 2009-01-16 15:50

Sory, namieszałem :(

Powinno by na odwrot:

cos(alfa) = x/r
sin (alfa = y/r

i

t = r * sin (alfa)
x = r * cos (alfa)

misiu_mietowy 2009-01-16 15:47

Ad zuza86

W kodzie wykorzystany jest "aparat matematyczny" na poziomie szkoły średniej :)
Każdy punkt w układzie współrzęnych x-y możemy przedstawić za pomocą modułu (odległości od punktu 0,0) i kąta między:
odcinkiem łączącym dany punkt x,y z punktem 0,0
a
osią x

Narysuj sobie na kartce układ współrzędnych x-y i zaznacz jakiś punkt (najlepiej w 1szej ćwiartce układu). Połącz odcinkiem ten punkt z punktem 0,0.
zaznacz kąt alfa między osią x a odcinkiem.
teraz widać, że:

sin (alfa) = x/r
cos (alfa = y/r

r - długosc odcinka.

Zatem x = r * sin (alfa)
          y = r * cos (alfa)

dla tego w równaniach na x i y pojawiają się sinus i cosinus :)

trejder 2008-06-02 12:56

Po wprowadzeniu prostej modyfikacji w kodzie rysującym wskazówkę godzinową, tzn. linijki:

x := Round(cos(PI * (30 * h - 90) / 180) * (R - (R / 100 * 30)) + Left + R);
y := Round(sin(PI * (30 * h - 90) / 180) * (R - (R / 100 * 30)) + Top + R);

uzupełniamy do postaci:

x := Round(cos(PI * (30 * h + (m / 2) - 90) / 180) * (R - (R / 100 * 30)) + Left + R);
y := Round(sin(PI * (30 * h + (m / 2) - 90) / 180) * (R - (R / 100 * 30)) + Top + R);

otrzymujemy w efekcie prawidłowe wychylanie się wskazówki godzinowej, w zależności do tego, która "część" godziny jest aktualnie. W nowej wersji wskazówka godzinowa "spaceruje" pomiędzy poprzednią, a następną godziną. Zaś w oryginale - przeskakuje, gdy jest pełna godzina, na nową wartość (np. pomiędzy 9, a 10), gdzie pozostaje nieruchomo przez całą godzinę.

Dzięki tej drobnej zmianie zegar ów pracuje bardziej, jak realistyczny.

zuza86 2006-06-05 20:09

bardzo fajny program tylko trochę za trudny dla osób które poruszają się po delphi mniej swobodnie... i nie za pewnie...

PiXel 2006-05-22 14:43

Komentarze mile widziane