How to make a Digital clock in delphi7?
Asked Answered
F

3

9

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

Florenceflorencia answered 28/2, 2012 at 18:15 Comment(2)
May I suggest your next exercise: an analog clock, much more fun!Scrimshaw
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!Uncanny
S
44

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;

Seven-segment digital clock

Playing with the GDI brushes:

Seven-segment digital clock

Scrimshaw answered 28/2, 2012 at 18:17 Comment(13)
+1 If you are unlucky it could advance 2 seconds in a single update. A smaller interval could solve that.Jabe
For fun, you should at least change from using a boring old TLabel to a 7 segment "LED". :-)Herdsman
Also works as a sheet of glass.Scrimshaw
Hm, still boring, what about analog clock with GDI animated cuckoo :-) (+1, nice work)Stanford
@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...Scrimshaw
+1 Nice exposition of how one could get to the final goal with a few try outs.Seamaid
+1 BTW, TDigitData could have been an Integer (representing 7 bit pattern)Nopar
@kobik: Now that you say that... of course! Too bad that you cannot enter binary numbers in Delphi source code, though...Scrimshaw
Oh 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..Hazing
+1,hey Self.DoubleBuffered:=true; will get rid of the flicker :)Mackinaw
@PresleyDias: Yes, that is true. Since I didn't see any flickering on my system, I didn't mention it, though.Scrimshaw
@WarrenP What LEDs?? Thats too modern for my tastes .. I prefer digital time displayed the way god intended - via Nixie tubes of course! en.wikipedia.org/wiki/Nixie_tubeWhom
very, very nice! Added a super small one to a TstatusBar to go with our Metro overhaul!Parlor
S
16

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;

DigitalClock.png

Seamaid answered 29/2, 2012 at 1:10 Comment(0)
W
1

Here are my clock's features:

  1. Time's accuracy 100%.
  2. Date is also added.
  3. 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;

enter image description here

Wengert answered 15/5, 2013 at 22:22 Comment(1)
Well, 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.Seamaid

© 2022 - 2024 — McMap. All rights reserved.