在視窗應用程式開發的實務中,表格資料的視覺化呈現與時間控制功能是構建專業應用程式的兩大核心技能。無論是開發資料管理系統需要展示大量表格資料,或是建立互動遊戲需要精確的時間控制與動畫效果,StringGrid 表格控制項與 Timer 計時器元件都扮演關鍵角色。StringGrid 提供完整的二維資料展示能力,支援固定標題列、動態調整尺寸與儲存格樣式設定,讓開發者能夠輕鬆建立類似試算表的介面。Timer 則提供精確的時間控制機制,能夠週期性觸發事件,實現從簡單的時鐘顯示到複雜的動畫效果。本文將從基礎概念開始,逐步深入到進階應用,涵蓋 StringGrid 的屬性設定與操作技巧、二維陣列與表格的整合應用、TDateTime 日期時間處理機制,以及 Timer 計時器的多樣化應用場景,幫助您全面掌握這兩個強大元件的開發能力。
StringGrid 表格控制項的核心架構
StringGrid 是 Delphi 提供的表格資料展示元件,它將資料組織為行與列的網格結構,每個儲存格可以包含文字內容。與簡單的標籤或文字方塊相比,StringGrid 提供結構化的資料呈現方式,特別適合展示陣列資料、資料庫查詢結果或任何需要表格形式呈現的資訊。
StringGrid 的基本結構包含行與列兩個維度。行從上到下排列,列從左到右排列。每個儲存格透過行索引與列索引定位,索引從 0 開始計數。第一個索引表示列位置,第二個索引表示行位置,因此 Cells[0, 0] 代表左上角的第一個儲存格。
固定區域是 StringGrid 的重要特性。固定行通常顯示在表格頂部作為欄位標題,固定列通常顯示在表格左側作為行標題。這些固定區域在使用者捲動表格時保持可見,提供持續的參考資訊。固定區域與一般資料區域可以設定不同的背景顏色,增強視覺區分。
procedure InitializeBasicGrid;
begin
sgdData.ColCount := 5;
sgdData.RowCount := 10;
sgdData.FixedCols := 1;
sgdData.FixedRows := 1;
sgdData.FixedColor := clSkyBlue;
sgdData.Color := clWhite;
sgdData.DefaultColWidth := 80;
sgdData.DefaultRowHeight := 25;
sgdData.Cells[0, 0] := '編號';
sgdData.Cells[1, 0] := '姓名';
sgdData.Cells[2, 0] := '分數';
sgdData.Cells[3, 0] := '等級';
sgdData.Cells[4, 0] := '備註';
end;
這個初始化過程展示 StringGrid 的基本設定。ColCount 設定總列數為 5,RowCount 設定總行數為 10。FixedCols 與 FixedRows 各設為 1,表示第一列與第一行為固定區域。FixedColor 設定固定區域的背景顏色為天藍色,Color 設定一般儲存格的背景顏色為白色。DefaultColWidth 與 DefaultRowHeight 分別設定預設的列寬與行高。最後使用 Cells 屬性設定第一行的標題文字。
ColCount 與 RowCount 屬性決定表格的尺寸。這兩個屬性可以在設計階段或執行階段設定,執行階段調整時表格會自動重新繪製。增加尺寸時新增的儲存格為空白,減少尺寸時超出範圍的資料會被丟棄。
procedure ResizeGrid(NewCols, NewRows: Integer);
begin
if (NewCols > 0) and (NewRows > 0) then
begin
sgdData.ColCount := NewCols;
sgdData.RowCount := NewRows;
StatusBar1.SimpleText := Format('表格大小: %d 列 x %d 行', [NewCols, NewRows]);
end
else
ShowMessage('列數與行數必須大於 0');
end;
這個過程接受新的列數與行數參數,在驗證有效性後調整表格尺寸。if 條件確保尺寸為正數,避免無效的表格設定。調整完成後在狀態列顯示新的表格尺寸。這種動態調整能力讓應用程式根據資料量自動調整顯示空間。
Cells 屬性是存取儲存格內容的主要介面。它是一個二維字串陣列,第一個索引為列,第二個索引為行。讀取 Cells 取得儲存格的文字內容,寫入 Cells 設定儲存格的文字。
procedure FillSampleData;
var
Row, Col: Integer;
begin
for Row := 1 to sgdData.RowCount - 1 do
begin
sgdData.Cells[0, Row] := IntToStr(Row);
sgdData.Cells[1, Row] := 'Student' + IntToStr(Row);
sgdData.Cells[2, Row] := IntToStr(Random(101));
if StrToInt(sgdData.Cells[2, Row]) >= 60 then
sgdData.Cells[3, Row] := '及格'
else
sgdData.Cells[3, Row] := '不及格';
end;
end;
這個過程填充範例資料到表格。外層迴圈遍歷所有資料行(從 1 開始跳過標題行)。對每一行,設定編號、姓名與隨機分數。然後根據分數判斷等級,60 分以上標示為及格,否則為不及格。這展示如何使用迴圈批次填充資料並實現簡單的條件邏輯。
DefaultColWidth 與 DefaultRowHeight 設定新建儲存格的預設尺寸。這些屬性只影響新增的儲存格,已存在的儲存格尺寸不會改變。若要調整特定列或行的尺寸,應該使用 ColWidths 與 RowHeights 陣列屬性。
procedure AdjustColumnWidths;
begin
sgdData.ColWidths[0] := 50;
sgdData.ColWidths[1] := 120;
sgdData.ColWidths[2] := 60;
sgdData.ColWidths[3] := 80;
sgdData.ColWidths[4] := 150;
end;
這個過程設定各列的寬度。ColWidths 是整數陣列,索引對應列號。第一列(編號)設為較窄的 50 像素,第二列(姓名)設為 120 像素提供足夠空間,第三列(分數)只需 60 像素,第四列(等級)為 80 像素,最後一列(備註)設為最寬的 150 像素。這種精確控制讓表格呈現更專業整齊。
@startuml
!define DISABLE_LINK
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
class StringGrid {
+ColCount: Integer
+RowCount: Integer
+FixedCols: Integer
+FixedRows: Integer
+DefaultColWidth: Integer
+DefaultRowHeight: Integer
+FixedColor: TColor
+Color: TColor
+Cells[ACol, ARow]: String
+ColWidths[Index]: Integer
+RowHeights[Index]: Integer
+GridLineWidth: Integer
}
note right of StringGrid
表格控制項
儲存格索引從 0 開始
Cells[列索引, 行索引]
end note
note bottom of StringGrid
固定區域用於標題
在捲動時保持可見
end note
@enduml
二維陣列與 StringGrid 的整合
二維陣列是表格資料在記憶體中的自然表示方式。將二維陣列的資料展示在 StringGrid 上是常見需求,需要理解陣列索引與儲存格索引的對應關係。
Pascal 的二維陣列可以透過兩種方式宣告。第一種是直接宣告二維陣列,第二種是宣告陣列的陣列。後者在概念上更清晰,把二維陣列視為多個一維陣列的集合。
const
MaxRows = 10;
MaxCols = 5;
type
TRowData = array[1..MaxCols] of Integer;
TTableData = array[1..MaxRows] of TRowData;
var
GridData: TTableData;
這段程式碼定義二維陣列類型。首先定義常數指定陣列的維度。TRowData 定義單行資料,包含 MaxCols 個整數。TTableData 定義完整表格,包含 MaxRows 個 TRowData。這種層次化定義讓陣列結構更清晰,也便於傳遞給程式處理。
填充陣列資料通常使用巢狀迴圈。外層迴圈遍歷行,內層迴圈遍歷列,確保每個元素都被處理。
procedure FillArrayWithRandomData(var Data: TTableData);
var
Row, Col: Integer;
begin
Randomize;
for Row := 1 to MaxRows do
begin
for Col := 1 to MaxCols do
begin
Data[Row][Col] := Random(201) - 100;
end;
end;
end;
這個過程用隨機資料填充二維陣列。Randomize 初始化隨機數產生器確保每次執行產生不同的序列。巢狀迴圈遍歷陣列的每個位置,Random(201) 產生 0 到 200 的隨機數,減去 100 得到 -100 到 100 的範圍。這種範圍設定在模擬測試資料時很有用。
將陣列資料轉移到 StringGrid 需要注意索引轉換。Pascal 陣列通常從 1 開始索引,而 StringGrid 的 Cells 索引從 0 開始。需要在轉換時調整索引值。
procedure DisplayArrayInGrid(const Data: TTableData);
var
Row, Col: Integer;
begin
sgdData.RowCount := MaxRows + 1;
sgdData.ColCount := MaxCols + 1;
sgdData.FixedCols := 1;
sgdData.FixedRows := 1;
for Col := 1 to MaxCols do
sgdData.Cells[Col, 0] := 'Col ' + IntToStr(Col);
for Row := 1 to MaxRows do
begin
sgdData.Cells[0, Row] := 'Row ' + IntToStr(Row);
for Col := 1 to MaxCols do
begin
sgdData.Cells[Col, Row] := IntToStr(Data[Row][Col]);
end;
end;
end;
這個過程將二維陣列展示在 StringGrid 上。首先設定表格尺寸,行列數各加 1 提供標題空間。設定一列一行為固定區域作為標題。第一個迴圈填充欄位標題,第二個巢狀迴圈填充行標題與資料。Data[Row][Col] 的內容轉換為字串後寫入 Cells[Col, Row]。注意這裡陣列索引從 1 開始而 Cells 索引從 0 開始的對應關係。
處理陣列資料並將結果展示是常見模式。例如計算每行的統計資訊並附加在表格末尾。
procedure CalculateAndDisplayRowStatistics(const Data: TTableData);
var
Row, Col: Integer;
Sum, Count: Integer;
Average: Real;
begin
sgdData.ColCount := MaxCols + 2;
sgdData.Cells[MaxCols + 1, 0] := '平均值';
for Row := 1 to MaxRows do
begin
Sum := 0;
Count := 0;
for Col := 1 to MaxCols do
begin
Sum := Sum + Data[Row][Col];
Inc(Count);
end;
if Count > 0 then
Average := Sum / Count
else
Average := 0;
sgdData.Cells[MaxCols + 1, Row] := FormatFloat('0.00', Average);
end;
end;
這個過程計算每行資料的平均值並顯示在額外的列。首先增加一列用於顯示統計結果,設定該列的標題為「平均值」。對每一行,累加所有元素並計數,然後計算平均值。FormatFloat 將平均值格式化為兩位小數的字串。這種模式可以擴展到其他統計量如最大值、最小值或標準差。
@startuml
!define DISABLE_LINK
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
state "陣列資料展示流程" as display {
state "定義陣列結構" as define
state "填充陣列資料" as fill
state "設定表格尺寸" as size
state "填充標題列" as header
state "轉換資料格式" as convert
state "寫入儲存格" as write
[*] --> define
define --> fill
fill --> size
size --> header
header --> convert
convert --> write
write --> [*]
}
note right of convert
注意索引轉換
陣列從 1 開始
Cells 從 0 開始
end note
note right of write
使用 IntToStr
轉換數值為文字
end note
@enduml
TDateTime 日期時間處理機制
TDateTime 是 Delphi 處理日期時間的核心資料類型。它使用雙精度浮點數表示,整數部分代表自 1899 年 12 月 30 日以來的天數,小數部分代表當天的時間比例。
這種表示方式讓日期時間計算變得直覺。兩個 TDateTime 相減得到相差的天數。TDateTime 加上或減去數值得到未來或過去的日期時間。小數 0.5 代表正午,0.25 代表早上 6 點,0.75 代表下午 6 點。
procedure DemonstrateDateTimeArithmetic;
var
Today, Tomorrow, NextWeek: TDateTime;
DaysDiff: Integer;
begin
Today := Date;
Tomorrow := Today + 1;
NextWeek := Today + 7;
DaysDiff := Trunc(NextWeek - Today);
ShowMessage('今天: ' + DateToStr(Today));
ShowMessage('明天: ' + DateToStr(Tomorrow));
ShowMessage('下週: ' + DateToStr(NextWeek));
ShowMessage('天數差: ' + IntToStr(DaysDiff));
end;
這個過程展示 TDateTime 的基本運算。Date 函式回傳當前日期。Tomorrow 透過加 1 得到明天的日期。NextWeek 透過加 7 得到一週後的日期。計算 NextWeek 與 Today 的差得到天數,Trunc 函式取整數部分。DateToStr 將 TDateTime 轉換為可讀的日期字串。
取得當前日期時間是最基本的需求。Delphi 提供三個函式分別取得日期、時間或兩者。
procedure ShowCurrentDateTime;
var
CurrentDate, CurrentTime, CurrentDateTime: TDateTime;
begin
CurrentDate := Date;
CurrentTime := Time;
CurrentDateTime := Now;
Memo1.Lines.Add('當前日期: ' + DateToStr(CurrentDate));
Memo1.Lines.Add('當前時間: ' + TimeToStr(CurrentTime));
Memo1.Lines.Add('日期時間: ' + DateTimeToStr(CurrentDateTime));
end;
這個過程分別取得並顯示日期、時間與日期時間。Date 只回傳日期部分,小數部分為 0。Time 只回傳時間部分,整數部分為 0。Now 回傳完整的日期時間。三個轉換函式將 TDateTime 格式化為字串,格式遵循系統的地區設定。
DecodeDate 與 DecodeTime 函式將 TDateTime 分解為組成部分。DecodeDate 取得年月日,DecodeTime 取得時分秒毫秒。
procedure AnalyzeDateTime(ADateTime: TDateTime);
var
Year, Month, Day: Word;
Hour, Minute, Second, Millisecond: Word;
begin
DecodeDate(ADateTime, Year, Month, Day);
DecodeTime(ADateTime, Hour, Minute, Second, Millisecond);
Memo1.Lines.Add(Format('年: %d', [Year]));
Memo1.Lines.Add(Format('月: %d', [Month]));
Memo1.Lines.Add(Format('日: %d', [Day]));
Memo1.Lines.Add(Format('時: %d', [Hour]));
Memo1.Lines.Add(Format('分: %d', [Minute]));
Memo1.Lines.Add(Format('秒: %d', [Second]));
end;
這個過程分解並顯示日期時間的各個部分。DecodeDate 將日期分解為年月日三個 Word 變數。DecodeTime 將時間分解為時分秒毫秒四個 Word 變數。Format 函式格式化輸出,讓每個部分都標註清楚。這種分解在需要單獨操作某個時間單位時很有用。
EncodeDate 與 EncodeTime 函式從組成部分建構 TDateTime。EncodeDate 接受年月日建立日期,EncodeTime 接受時分秒毫秒建立時間。
procedure CreateSpecificDateTime;
var
Birthday, MeetingTime, Appointment: TDateTime;
begin
Birthday := EncodeDate(1990, 5, 15);
MeetingTime := EncodeTime(14, 30, 0, 0);
Appointment := Birthday + MeetingTime;
ShowMessage('生日: ' + DateToStr(Birthday));
ShowMessage('會議時間: ' + TimeToStr(MeetingTime));
ShowMessage('約會: ' + DateTimeToStr(Appointment));
end;
這個過程使用 Encode 函式建立特定的日期時間。EncodeDate 建立 1990 年 5 月 15 日的日期。EncodeTime 建立 14:30:00 的時間。將兩者相加得到完整的日期時間,代表那天下午 2:30 的時刻。這種精確建構在處理預約、排程或歷史資料時很重要。
FormatDateTime 函式提供靈活的日期時間格式化。它接受格式字串與 TDateTime 值,回傳格式化的字串。格式字串使用特殊符號指定輸出格式。
procedure ShowFormattedDateTime;
var
Now: TDateTime;
begin
Now := System.Now;
Memo1.Lines.Add(FormatDateTime('yyyy-mm-dd', Now));
Memo1.Lines.Add(FormatDateTime('hh:nn:ss', Now));
Memo1.Lines.Add(FormatDateTime('yyyy年mm月dd日', Now));
Memo1.Lines.Add(FormatDateTime('dddd, mmmm dd, yyyy', Now));
Memo1.Lines.Add(FormatDateTime('hh:nn AM/PM', Now));
end;
這個過程展示多種日期時間格式。yyyy 代表四位年份,mm 代表兩位月份,dd 代表兩位日期。hh 代表小時,nn 代表分鐘,ss 代表秒。dddd 代表完整星期名稱,mmmm 代表完整月份名稱。AM/PM 加入上下午標示。這種靈活格式化能適應不同的顯示需求。
DayOfWeek 函式回傳星期幾的數值。1 代表星期日,2 代表星期一,依此類推到 7 代表星期六。
procedure ShowDayOfWeek(ADate: TDateTime);
var
DayNum: Integer;
DayName: String;
begin
DayNum := DayOfWeek(ADate);
case DayNum of
1: DayName := '星期日';
2: DayName := '星期一';
3: DayName := '星期二';
4: DayName := '星期三';
5: DayName := '星期四';
6: DayName := '星期五';
7: DayName := '星期六';
end;
ShowMessage(DateToStr(ADate) + ' 是 ' + DayName);
end;
這個過程判斷並顯示日期是星期幾。DayOfWeek 回傳數值,case 陳述式將數值轉換為中文星期名稱。這種轉換在建立行事曆或排程系統時經常用到。
@startuml
!define DISABLE_LINK
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
state "TDateTime 處理流程" as datetime {
state "取得日期時間" as get
state "解析組成部分" as decode
state "建構日期時間" as encode
state "格式化顯示" as format
state "執行運算" as calc
[*] --> get
get --> decode: DecodeDate/DecodeTime
get --> format: FormatDateTime
get --> calc: 加減運算
decode --> encode: EncodeDate/EncodeTime
encode --> format
calc --> format
format --> [*]
}
note right of decode
分解為
年月日時分秒
end note
note right of encode
從組成部分
建構日期時間
end note
@enduml
Timer 計時器元件的核心機制
Timer 計時器是週期性觸發事件的元件。它在背景執行,當指定時間間隔到達時觸發 OnTimer 事件,讓開發者能夠執行特定程式碼。計時器是不可見元件,在執行時不會出現在使用者介面上。
計時器的核心屬性是 Interval 與 Enabled。Interval 指定觸發間隔,單位為毫秒。1000 毫秒等於 1 秒,因此設定 Interval 為 1000 表示每秒觸發一次。Enabled 控制計時器是否運作,True 表示啟動,False 表示停止。
procedure InitializeTimer;
begin
Timer1.Interval := 1000;
Timer1.Enabled := False;
end;
procedure TForm1.btnStartClick(Sender: TObject);
begin
Timer1.Enabled := True;
btnStart.Enabled := False;
btnStop.Enabled := True;
end;
procedure TForm1.btnStopClick(Sender: TObject);
begin
Timer1.Enabled := False;
btnStart.Enabled := True;
btnStop.Enabled := False;
end;
這個範例展示計時器的基本控制。InitializeTimer 設定間隔為 1 秒並將計時器設為停止狀態。啟動按鈕的事件處理程式啟動計時器並調整按鈕狀態。停止按鈕的事件處理程式停止計時器並還原按鈕狀態。這種模式讓使用者完全控制計時器的運作。
OnTimer 事件是計時器的核心。每當時間間隔到達時,系統自動呼叫這個事件處理程式。程式碼可以在此執行任何需要週期性執行的任務。
procedure TForm1.Timer1Timer(Sender: TObject);
var
CurrentTime: TDateTime;
begin
CurrentTime := Now;
lblTime.Caption := FormatDateTime('hh:nn:ss', CurrentTime);
lblDate.Caption := FormatDateTime('yyyy-mm-dd', CurrentTime);
end;
這個事件處理程式實現簡單的時鐘功能。每次觸發時取得當前時間,格式化為時間字串與日期字串,分別顯示在兩個標籤上。如果 Interval 設為 1000,時鐘每秒更新一次,顯示當前的精確時間。
建立動畫效果是計時器的重要應用。透過週期性改變元件的屬性,可以創造平滑的視覺動畫。
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if Shape1.Left < Form1.ClientWidth then
Shape1.Left := Shape1.Left + 5
else
Shape1.Left := 0;
end;
這個事件處理程式讓圖形從左向右移動。每次觸發時檢查圖形的水平位置,如果還沒到達表單右邊界,就向右移動 5 個像素。當到達右邊界時,重置到左邊重新開始。如果 Interval 設為 50 毫秒,這個移動看起來會非常平滑。
計時器可以實現倒數計時功能。維護一個計數器變數,每次觸發時遞減,到達零時執行特定動作。
var
CountdownSeconds: Integer;
procedure TForm1.btnStartCountdownClick(Sender: TObject);
begin
CountdownSeconds := StrToInt(edtSeconds.Text);
Timer1.Interval := 1000;
Timer1.Enabled := True;
btnStartCountdown.Enabled := False;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Dec(CountdownSeconds);
lblCountdown.Caption := IntToStr(CountdownSeconds);
if CountdownSeconds <= 0 then
begin
Timer1.Enabled := False;
ShowMessage('時間到!');
btnStartCountdown.Enabled := True;
end;
end;
這個倒數計時器從使用者輸入的秒數開始倒數。按鈕事件取得初始秒數並啟動計時器。計時器事件每秒遞減計數器並更新顯示。當計數器到達或低於零時,停止計時器並顯示提示訊息。這種模式適合測驗、遊戲或任何需要時間限制的應用。
多個計時器可以協同工作實現複雜的時間控制。每個計時器有獨立的間隔與事件處理程式,可以執行不同的任務。
procedure TForm1.btnStartAnimationClick(Sender: TObject);
begin
Timer1.Interval := 50;
Timer1.Enabled := True;
Timer2.Interval := 10000;
Timer2.Enabled := True;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
lblStatus.Left := lblStatus.Left + 3;
if lblStatus.Left > Form1.ClientWidth then
lblStatus.Left := 0;
end;
procedure TForm1.Timer2Timer(Sender: TObject);
begin
Timer1.Enabled := False;
Timer2.Enabled := False;
ShowMessage('動畫結束');
end;
這個範例使用兩個計時器。Timer1 每 50 毫秒觸發一次,讓標籤持續向右移動。Timer2 每 10 秒觸發一次,在 10 秒後停止動畫。這種多計時器協作模式可以實現更複雜的時間控制邏輯。
建立視覺效果變化是計時器的創意應用。週期性改變顏色、大小或位置可以吸引使用者注意或增加介面活力。
procedure TForm1.Timer1Timer(Sender: TObject);
var
R, G, B: Integer;
begin
R := Random(256);
G := Random(256);
B := Random(256);
Panel1.Color := RGB(R, G, B);
end;
這個事件處理程式讓面板的背景顏色隨機變化。每次觸發時產生三個 0 到 255 的隨機數代表紅綠藍色彩分量,使用 RGB 函式組合成顏色值並設定給面板。如果間隔設為 500 毫秒,面板每半秒變換一次顏色,創造動態的視覺效果。
整合應用:數位時鐘與資料監控
整合 StringGrid、TDateTime 與 Timer 可以建立實用的應用程式。數位時鐘是經典範例,展示如何使用計時器週期性更新時間顯示。
procedure TForm1.FormCreate(Sender: TObject);
begin
Timer1.Interval := 1000;
Timer1.Enabled := True;
lblClock.Font.Size := 36;
lblClock.Font.Style := [fsBold];
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
CurrentDateTime: TDateTime;
Year, Month, Day, DOW: Word;
DayName: String;
begin
CurrentDateTime := Now;
lblClock.Caption := FormatDateTime('hh:nn:ss', CurrentDateTime);
lblDate.Caption := FormatDateTime('yyyy年mm月dd日', CurrentDateTime);
DecodeDate(CurrentDateTime, Year, Month, Day);
DOW := DayOfWeek(CurrentDateTime);
case DOW of
1: DayName := '星期日';
2: DayName := '星期一';
3: DayName := '星期二';
4: DayName := '星期三';
5: DayName := '星期四';
6: DayName := '星期五';
7: DayName := '星期六';
end;
lblDayOfWeek.Caption := DayName;
end;
這個數位時鐘在表單建立時啟動計時器。計時器事件每秒取得當前時間,格式化為時間字串顯示在大字體標籤上,格式化為日期字串顯示在日期標籤上。使用 DayOfWeek 判斷星期幾並顯示在另一個標籤上。這個完整的時鐘提供時間、日期與星期資訊。
資料監控系統是另一個實用應用,使用 StringGrid 顯示監控資料,用 Timer 定期更新。
var
DataLog: array[1..100] of record
Time: TDateTime;
Value: Real;
end;
LogCount: Integer = 0;
procedure TForm1.Timer1Timer(Sender: TObject);
var
NewValue: Real;
Row: Integer;
begin
NewValue := Random * 100;
Inc(LogCount);
if LogCount > 100 then
LogCount := 100;
DataLog[LogCount].Time := Now;
DataLog[LogCount].Value := NewValue;
sgdMonitor.RowCount := LogCount + 1;
for Row := 1 to LogCount do
begin
sgdMonitor.Cells[0, Row] := IntToStr(Row);
sgdMonitor.Cells[1, Row] := FormatDateTime('hh:nn:ss', DataLog[Row].Time);
sgdMonitor.Cells[2, Row] := FormatFloat('0.00', DataLog[Row].Value);
end;
end;
這個資料監控系統每隔一段時間產生新的監控數值。計時器事件產生隨機數值代表監控資料,記錄到陣列中連同時間戳記。然後更新 StringGrid 的內容,顯示所有記錄的序號、時間與數值。這種模式可以擴展到真實的感測器資料監控或系統效能監控。
持續精進與實務開發
透過對 StringGrid 表格控制項與 Timer 計時器元件的深入學習,我們掌握資料視覺化與時間控制的核心技術。StringGrid 提供靈活的表格展示能力,支援動態調整、自訂格式與資料繫結。Timer 提供精確的時間控制,能實現週期性任務、動畫效果與倒數計時。TDateTime 的日期時間處理機制讓時間相關運算變得簡單直覺。
但學習不應止步於此。現代應用程式面對更複雜的需求,包括 StringGrid 的進階功能如儲存格合併、條件格式化、排序與篩選。計時器的高精度應用如多媒體同步、遊戲循環控制。資料庫與表格的整合讓 StringGrid 能展示大量資料。這些進階主題值得進一步探索。
實務專案開發整合所有學到的技術。建立資料分析工具使用 StringGrid 展示統計結果。開發專案管理系統整合時間追蹤與甘特圖顯示。實作監控儀表板即時顯示系統狀態。建立教育軟體使用計時器實現互動測驗。這些專案將理論知識轉化為實際能力,累積解決問題的經驗,最終成為能夠開發專業應用程式的軟體工程師。