运行时如何触发StringGrid的OnCellDraw事件以刷新预订日期显示?
如何更新预订数组后刷新StringGrid的单元格绘制效果?
首先,核心需求很明确:当你点击按钮更新ar2Booking数组后,触发StringGrid重新执行OnCellDraw事件,刷新显示。其实实现起来非常简单,只需要在数组更新完成后调用StringGrid的**Invalidate**方法即可——这个方法会告诉控件它的显示内容已经过期,需要重新绘制所有单元格,自然就会触发你的OnCellDraw事件。
按钮点击事件示例代码
假设你的按钮用来处理用户的预订操作,代码可以这样写:
procedure TfrmClient.btnBookDateClick(Sender: TObject); var SelectedDay, SelectedMonth: Integer; begin // 这里示例获取用户在StringGrid中选中的日期(你可以根据实际场景替换成输入框选择等逻辑) SelectedDay := stgYearPlan1.Selection.Left; SelectedMonth := stgYearPlan1.Selection.Top; // 校验日期合法性,避免数组越界 if (SelectedDay in [1..31]) and (SelectedMonth in [1..12]) then begin // 更新预订状态,比如标记为'Y'表示已预订 ar2Booking[SelectedDay, SelectedMonth] := 'Y'; // 触发控件刷新,自动调用OnCellDraw stgYearPlan1.Invalidate; end; end;
顺便优化你的OnCellDraw事件(重要!)
看了你当前的OnCellDraw代码,有个很大的效率问题:每次绘制单个单元格时,都要循环遍历31天×12个月的所有日期,而且还重复初始化表头。这会导致控件绘制非常卡顿,尤其是StringGrid内容较多的时候。
建议你把表头初始化逻辑移到窗体创建事件里(只执行一次):
procedure TfrmClient.FormCreate(Sender: TObject); var k: Integer; begin // 初始化日期和月份表头,仅在窗体启动时执行一次 for k := 1 to 31 do stgYearPlan1.Cells[k, 0] := IntToStr(k); for k := 1 to 12 do stgYearPlan1.Cells[0, k] := ShortMonthNames[k]; end;
然后简化OnCellDraw事件,直接针对当前要绘制的单元格(ACol和ARow)判断状态,不需要循环所有日期:
procedure TfrmClient.stgYearPlan1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); var BookingStatus: string; begin // 跳过表头行和列,不用处理绘制 if (ACol = 0) or (ARow = 0) then Exit; BookingStatus := ar2Booking[ACol, ARow]; // 根据预订状态设置单元格样式 if BookingStatus = 'Y' then begin stgYearPlan1.Canvas.Brush.Color := clBlack; stgYearPlan1.Canvas.FillRect(Rect); // 黑色背景上要把文字设为白色,不然看不到内容 stgYearPlan1.Canvas.Font.Color := clWhite; stgYearPlan1.Canvas.TextOut(Rect.Left, Rect.Top, stgYearPlan1.Cells[ACol, ARow]); end else if BookingStatus = 'D' then begin stgYearPlan1.Canvas.Brush.Color := clSilver; stgYearPlan1.Canvas.FillRect(Rect); stgYearPlan1.Canvas.TextOut(Rect.Left + 2, Rect.Top + 2, stgYearPlan1.Cells[ACol, ARow]); end else begin // 绘制默认样式,避免单元格残留之前的绘制痕迹 stgYearPlan1.Canvas.Brush.Color := stgYearPlan1.Color; stgYearPlan1.Canvas.FillRect(Rect); stgYearPlan1.Canvas.Font.Color := stgYearPlan1.Font.Color; stgYearPlan1.Canvas.TextOut(Rect.Left, Rect.Top, stgYearPlan1.Cells[ACol, ARow]); end; end;
这样修改后,不仅刷新效率会大幅提升,显示效果也会更稳定。
内容的提问来源于stack exchange,提问作者user13898928
相关产品推荐
相关产品推荐

