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;
Komentarze mile widziane
bardzo fajny program tylko trochę za trudny dla osób które poruszają się po delphi mniej swobodnie... i nie za pewnie...
Sory, namieszałem :(
Powinno by na odwrot:
cos(alfa) = x/r
sin (alfa = y/r
i
t = r sin (alfa)
x = r cos (alfa)
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ę
a jak zrobić, żeby nam się to robiło na obiekcie Image , a nie na formie??
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.
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 :)