如何在Delphi TGrid Firemonkey组件中更改单元格的颜色?

5

我以TGrid列中的单元格为例。组件选项中没有颜色属性。颜色只能通过代码访问。代码必须在“绘制列单元格”事件中使用,但是需要什么样的代码呢?我尝试使用与VCL组件相同的过程,但是FMX中的Tcanvas不包括刷子属性。该网站上的其他类似问题只是猜测如何处理颜色。

是否有人成功更改了单元格(或其他组件)的背景色?


请查看 http://stackoverflow.com/questions/39956166/fmx-delphi-berlin-how-to-change-font-color-in-rows-of-tgrid - RBA
VCL和FMX组件彼此不同,访问TGrid中的TColumn中的单元格只能通过代码访问。而单元格似乎不是一个组件(或类)。 - Ashlar
2个回答

8

FMX框架提供了几种改变TGrid背景外观的方法。以下介绍两种方法,即交替行颜色和单元格颜色。

交替行颜色,可选择使用样式

这是在TGrid.Options属性中存在的可预设布尔项,名为AlternateRowBackground。默认颜色为浅灰色($FFEEEEEE)。要更改此颜色,可以添加TStyleBook或右键单击网格并选择编辑自定义样式...编辑默认样式...,然后更改gridstyle-alternatingrowbackgroundColor属性。这里是一个将颜色更改为Bisque的示例:

enter image description here

OnDrawColumnCell事件中的代码

这个事件会为网格的每个单元格调用一次,并提供完全控制绘制单元格背景的功能。事件处理程序的标题如下:

procedure TForm11.Grid1DrawColumnCell(Sender: TObject; const Canvas: TCanvas;
  const Column: TColumn; const Bounds: TRectF; const Row: Integer;
  const Value: TValue; const State: TGridDrawStates);

为了绘制图形,我们需要一个 TBrush,因此我们将其声明为本地变量:
var
  bgBrush: TBrush;

现在我们准备应用一些特殊背景绘制的场景。首先是如何让默认绘制出现在某些单元格状态下。

  if (TGridDrawState.Selected in State) or
      (TGridDrawState.Focused in State) then
  begin
    Grid1.DefaultDrawColumnCell(Canvas, Column, Bounds, Row, Value, State);
    Exit;
  end;

接下来我们需要用到TBrush,因此我们创建它并管理其生命周期(在Windows平台上):

  bgBrush:= TBrush.Create(TBrushKind.Solid, TAlphaColors.White); // default white color
  try
  //
  // following code snippets go in here
  //
  finally
    bgBrush.Free;
  end;

接下来是一个无需使用样式绘制交替行背景的示例

  if Odd(Row) then
    bgBrush.Color := TAlphaColors.MoneyGreen+$202020; // a very light green color
  Canvas.FillRect(Bounds, 0, 0, [], 1, bgBrush);

给定列的背景颜色示例:
  case Column.Index of
    0: bgBrush.Color := TAlphaColors.lightBlue;
    1: bgBrush.Color := TAlphaColors.MoneyGreen;
  end;
  Canvas.FillRect(Bounds, 0, 0, [], 1, bgBrush);

最后,这是一个由数据值决定背景颜色的示例。

  if Column.Index = 1 then
    if Value.AsOrdinal < 0 then  // negative 
      bgBrush.Color := TAlphaColors.Lightpink
    else
      bgBrush.Color := TAlphaColors.MoneyGreen;
  Canvas.FillRect(Bounds, 0, 0, [], 1, bgBrush);

并提供一个样例图片:

enter image description here

文本颜色如此答案所示。


感谢您提供了一个很好的详细答案! - Ashlar
我在一个项目中测试了你的答案,发现FillRect遮盖了文本值。如果我选择单元格进行编辑,数据是存在的,但是一旦我将焦点更改到另一个单元格,它就会消失。隐藏效果适用于所有列,无论是否着色。 - Ashlar
当您使用OnDrawColumnCell()事件时,需要首先安排背景颜色的绘制,然后再进行文本绘制。即先使用FillRect()函数进行绘制,然后使用FillText()函数。 - Tom Brunberg
不幸的是,这是在drawcolumncell方法调用中。我不认为我知道任何时候哪个单元格在调用它,有哪些其他参数适用于特定调用,也不知道要放置什么文本。我应该问另一个问题吗? - Ashlar
为什么你说“不幸的是...”,我们都在谈论例如procedure TForm11.Grid1DrawColumnCell(),不是吗?当我说OnDrawColumnCell时,我是在谈论属性,IDE会将过程名称Grid1DrawColumnCell分配给该属性。如果这不清楚,您需要针对此问题提出一个新问题,但首先请阅读文档。在我上面的答案结尾处,有一个关于文本颜色的问题的链接,其中显示了FillText()方法的用法。 - Tom Brunberg
显示剩余2条评论

2
请看这个例子。注释中有解释:
procedure TfrmOperationTab1.strgridHeartbeatsDrawColumnCell(Sender: TObject;
  const Canvas: TCanvas; const Column: TColumn; const Bounds: TRectF;
  const Row: Integer; const Value: TValue; const State: TGridDrawStates);
var
  bgBrush: TBrush;
begin
  try
    // if a cell contains word 'WARNING' then we want to paint its background in Pink color
    if Value.AsString.Contains('WARNING') then
    begin
      // Create pink brush
      bgBrush:= TBrush.Create(TBrushKind.Solid, TAlphaColors.Lightpink);
      // Paint the whole area
      Canvas.FillRect(Bounds, 0, 0, [], 1, bgBrush);
      bgBrush.Free;
    end;
  finally
  end;
  // IMPORTANT: let system draw all the other staff. If not called, then you wont see the content of your cell
  Column.DefaultDrawCell(Canvas, Bounds, Row, Value, State);
end;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接