I am pretty new to delphi , and would like to start with something easy . Could someone please show me an example how to make a Digital clock that will transfer the "time" ( hour , min , sec ) to a label ? Or something like that
-
12May I suggest your next exercise: an *analog* clock, much more fun! – Andreas Rejbrand Feb 28 '12 at 18:38
-
Happy to see the question is not just down-voted saying the user did not do sufficient research and is not a real question etc. And I the answers also. Very nice! – ssh May 16 '13 at 16:28
3 Answers
Exercise 1
Drop a TLabel
and a TButton
on your form.
Double-click the button, and write
procedure TForm1.Button1Click(Sender: TObject);
begin
Label1.Caption := TimeToStr(Time);
end;
Exercise 2
To get the time to update automatically, add a TTimer
to your form, and double-click it (you can remove the button if you like). Then write
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Label1.Caption := TimeToStr(Time);
end;
This code will run once a second (the default interval for a TTimer
, which is perfect for us, so we do not need to change it).
Exercise 3
To make the clock more annoying, you can try this: in the interface of your form, add a private field called FHighlight
, like this:
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
Timer1: TTimer;
procedure Button1Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
FHighlight: boolean;
public
{ Public declarations }
end;
Now you can do
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Label1.Caption := TimeToStr(Time);
if FHighlight then
begin
Label1.Color := clWhite;
Label1.Font.Color := clBlack;
end
else
begin
Label1.Color := clBlack;
Label1.Font.Color := clWhite;
end;
FHighlight := not FHighlight;
end;
In order for this effect to work, you need to change one of the properties of the TLabel
control (design-time). Change Transparent
to false
, using the Object Inspector, if it isn't already.
Update (Exercise 4)
Since Warren P thinks it is too boring with a plain TLabel
, this is how you can achieve a 'true' seven-segment digital clock:
procedure TForm1.FormPaint(Sender: TObject);
type
TDigitData = array[0..6] of boolean;
TPhysDigit = array[0..7] of TRect;
const
DIGIT: array[0..9] of TDigitData =
(
(true, true, true, true, true, true, false),
(false, true, true, false, false, false, false),
(true, true, false, true, true, false, true),
(true, true, true, true, false, false, true),
(false, true, true, false, false, true, true),
(true, false, true, true, false, true, true),
(true, false, true, true, true, true, true),
(true, true, true, false, false, false, false),
(true, true, true, true, true, true, true),
(true, true, true, true, false, true, true)
);
var
PaddingW,
PaddingH,
UnitX,
UnitY,
DigitWidth,
DigitHeight,
BarLengthX,
BarLengthY,
DigitSeparation,
FieldSeparation: integer;
SEGMENTS: array[0..5] of TPhysDigit;
i: Integer;
function TranslatePhysDigit(const PhysDigit: TPhysDigit; const DX: integer; const DY: integer = 0): TPhysDigit;
var
i: Integer;
begin
for i := 0 to 7 do
begin
result[i].Left := PhysDigit[i].Left + DX;
result[i].Right := PhysDigit[i].Right + DX;
result[i].Top := PhysDigit[i].Top + DY;
result[i].Bottom := PhysDigit[i].Bottom + DY;
end;
end;
procedure DrawDigit(const Position, Value: integer);
var
i: integer;
begin
for i := 0 to 6 do
if DIGIT[Value, i] then
Canvas.FillRect(SEGMENTS[Position, i]);
end;
procedure DrawColon(const Position: integer);
var
ColonRect1: TRect;
ColonRect2: TRect;
begin
ColonRect1 := Rect(PaddingW + Position*UnitX, PaddingH + UnitY,
PaddingW + (Position+1)*UnitX, PaddingH + 2*UnitY);
ColonRect2 := Rect(PaddingW + Position*UnitX, PaddingH + 3*UnitY,
PaddingW + (Position+1)*UnitX, PaddingH + 4*UnitY);
Canvas.FillRect(ColonRect1);
Canvas.FillRect(ColonRect2);
end;
var
t: string;
begin
PaddingW := Width div 20;
PaddingH := Height div 20;
UnitX := (ClientWidth - 2*PaddingW) div 27;
UnitY := (ClientHeight - 2*PaddingH) div 5;
DigitWidth := 3*UnitX;
DigitHeight := 5*UnitY;
BarLengthX := 3*UnitX;
BarLengthY := 3*UnitY;
DigitSeparation := 4*UnitX;
FieldSeparation := 6*UnitX;
SEGMENTS[0, 0] := Rect(0, 0, DigitWidth, UnitY);
SEGMENTS[0, 1] := Rect(DigitWidth - UnitX, 0, DigitWidth, BarLengthY);
SEGMENTS[0, 2] := Rect(DigitWidth - UnitX, 2*UnitY, DigitWidth, DigitHeight);
SEGMENTS[0, 3] := Rect(0, DigitHeight - UnitY, DigitWidth, DigitHeight);
SEGMENTS[0, 4] := Rect(0, 2*UnitY, UnitX, DigitHeight);
SEGMENTS[0, 5] := Rect(0, 0, UnitX, BarLengthY);
SEGMENTS[0, 6] := Rect(0, 2*UnitY, DigitWidth, 3*UnitY);
SEGMENTS[0] := TranslatePhysDigit(SEGMENTS[0], PaddingW, PaddingH);
SEGMENTS[1] := TranslatePhysDigit(SEGMENTS[0], DigitSeparation);
SEGMENTS[2] := TranslatePhysDigit(SEGMENTS[1], FieldSeparation);
SEGMENTS[3] := TranslatePhysDigit(SEGMENTS[2], DigitSeparation);
SEGMENTS[4] := TranslatePhysDigit(SEGMENTS[3], FieldSeparation);
SEGMENTS[5] := TranslatePhysDigit(SEGMENTS[4], DigitSeparation);
Canvas.Brush.Color := clBlack;
Canvas.FillRect(ClientRect);
Canvas.Brush.Color := clBlack;
Canvas.FillRect(Rect(PaddingW, PaddingH, ClientWidth - PaddingW,
ClientHeight - PaddingH));
Canvas.Brush.Color := clRed;
t := FormatDateTime('hhnnss', Time);
for i := 0 to 5 do
DrawDigit(i, StrToInt(Copy(t, i+1, 1)));
if odd(StrToInt(Copy(t, 6, 1))) then
begin
DrawColon(8);
DrawColon(18);
end;
end;
procedure TForm1.FormResize(Sender: TObject);
begin
Invalidate;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Invalidate;
end;
Playing with the GDI brushes:

- 105,602
- 8
- 282
- 384
-
11+1 If you are unlucky it could advance 2 seconds in a single update. A smaller interval could solve that. – David Heffernan Feb 28 '12 at 18:22
-
3For fun, you should at least change from using a boring old TLabel to a 7 segment "LED". :-) – Warren P Feb 28 '12 at 19:37
-
4Also works [as a sheet of glass](http://privat.rejbrand.se/seven-segment-glass.png). – Andreas Rejbrand Feb 28 '12 at 21:33
-
3Hm, still boring, what about analog clock with GDI animated cuckoo :-) (+1, nice work) – TLama Feb 28 '12 at 22:26
-
2@TLama: I would have started on that right away, had it not been for the (sad) fact that I need to get up early tomorrow... – Andreas Rejbrand Feb 28 '12 at 22:38
-
1+1 Nice exposition of how one could get to the final goal with a few try outs. – NGLN Feb 29 '12 at 01:02
-
1+1 BTW, `TDigitData` could have been an Integer (representing 7 bit pattern) – kobik Feb 29 '12 at 11:48
-
@kobik: Now that you say that... of course! Too bad that you cannot enter binary numbers in Delphi source code, though... – Andreas Rejbrand Feb 29 '12 at 12:48
-
2Oh what a sweet tutorial.. we are so fortunate that we have some excellent teachers who would love to share.. thank you.. i love this tutorial.. – jimsweb Feb 29 '12 at 17:26
-
-
@PresleyDias: Yes, that is true. Since I didn't see any flickering on my system, I didn't mention it, though. – Andreas Rejbrand Mar 02 '12 at 08:26
-
@WarrenP What LEDs?? Thats too modern for my tastes .. I prefer digital time displayed the way god intended - via Nixie tubes of course! http://en.wikipedia.org/wiki/Nixie_tube – Peter M Mar 03 '12 at 01:21
-
very, very nice! Added a super small one to a TstatusBar to go with our Metro overhaul! – Peter Turner Apr 05 '13 at 19:52
Download my open source NLDDigiLabel component from here, place three of them on the form, place two common labels in between as time separators, and set the background color of the form. In this example, I did all this on a frame for convenience:
unit Unit2;
interface
uses
Windows, SysUtils, Classes, Graphics, Controls, Forms, StdCtrls, ExtCtrls,
NLDDigiLabel;
type
TDigitalClock = class(TFrame)
HoursLabel: TNLDDigiLabel;
MinsLabel: TNLDDigiLabel;
SecsLabel: TNLDDigiLabel;
TimeSeparator1: TLabel;
TimeSeparator2: TLabel;
Timer: TTimer;
procedure TimerTimer(Sender: TObject);
private
FTime: TTime;
procedure SetTime(Value: TTime);
public
property Time: TTime read FTime write SetTime;
end;
implementation
{$R *.dfm}
{ TDigitalClock }
procedure TDigitalClock.SetTime(Value: TTime);
var
Hours: Word;
Mins: Word;
Secs: Word;
MSecs: Word;
begin
if FTime <> Value then
begin
FTime := Value;
DecodeTime(FTime, Hours, Mins, Secs, MSecs);
HoursLabel.Value := Hours;
MinsLabel.Value := Mins;
SecsLabel.Value := Secs;
end;
end;
procedure TDigitalClock.TimerTimer(Sender: TObject);
begin
SetTime(FTime + 1/SecsPerDay);
end;
end.
Now, drop such a frame on your form, et voilá:
procedure TForm1.FormCreate(Sender: TObject);
begin
DigitalClock1.Time := Time;
end;

- 43,011
- 8
- 105
- 200
Here are my clock's features:
- Time's accuracy 100%.
- Date is also added.
- It is easy to make and doesn't take less than 2 minutes; just create a timer and 2 labels, and write this under implementation:
procedure TForm1.FormCreate(Sender: TObject);
begin
//Background,Clock's Settings
form1.Caption:='Digital Clock';
form1.Height:=260;
form1.Width:=750;
form1.BorderStyle:=bsToolWindow;
form1.Color:=clbackground;
//Label (Time,Date) Settings
label1.Font.Size:=72;
label1.Font.Color:=clred;
label1.Caption:='Time';
label1.Top:=0;
label1.Left:=8;
label2.Font.Size:=72;
label2.Font.Color:=clblue;
label2.Caption:='Date';
label2.Top:=104;
label2.Left:=8;
end;
//Create Clock,Calendar
procedure TForm1.Timer1Timer(Sender: TObject);
begin
label1.Caption:='Time: '+timetostr(time);
label2.Caption:='Date: '+datetostr(date);
timer1.Interval:=1; //100% Accuracy
end;

- 43,011
- 8
- 105
- 200

- 243
- 1
- 7
- 18
-
1Well, there's no such thing as 100% `TTimer` accuracy, neither will `OnTimer` at those intervals of 1 millisecond occur. And setting the interval in the `OnTimer` event is, well... remarkable. The -1 isn't mine though. – NGLN May 16 '13 at 11:40