You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

运行时如何触发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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 12:37:58