5

I use the example of the cell in a TGrid column as an example. There is no color property in the components option. THe color is only accessible by code. The code must go in the Draw Column Cell event, but what code does it? I attempted to use the same process as in VCL components, but the Tcanvas in FMX does not include a brush property. Other similar questions on the site do not provide more than speculations on how color is handled.

Has anyone successfully changed the background color in a cell (or other component)?

Ashlar
  • 636
  • 1
  • 10
  • 25
  • Take a look at http://stackoverflow.com/questions/39956166/fmx-delphi-berlin-how-to-change-font-color-in-rows-of-tgrid – RBA Apr 26 '17 at 07:24
  • VCL and FMX components differ from each other and accessing a cell in a Tcolumn in a TGrid can only be accessed through code. And a Cell does not appear to be a component (or a class). – Ashlar Apr 27 '17 at 02:18

2 Answers2

8

The FMX framework offers a couple of means to change the appearance of the background of a TGrid. Two means, alternating row colors and color per cell are presented in the following.

Alternating row colors, optionally using styles

This exists as a presetable boolean item in the TGrid.Options property named AlternateRowBackground. The default color is a light gray color ($FFEEEEEE). To change this color you can add a TStyleBook or right click the grid and select Edit Custom Style ... or Edit Default Style ... and then change the Color property of gridstyle - alternatingrowbackground. Here an example where the color is changed to Bisque:

enter image description here

Code in the OnDrawColumnCell event

This even is called for each cell of the grid and offers full control of painting the cell background. The header of the event handler looks like this:

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

For painting we will need a TBrush, so we declare one as a local variable:

var
  bgBrush: TBrush;

We are now ready to apply some scenarios of special background drawing. First is how to let the default drawing take place for certain cell states.

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

For the following we will need the TBrush, so we create it and manage its lifetime (on Windows platform):

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

Next, an example of painting alternating row backgrounds without using styles

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

Then an example of background color for given columns

  case Column.Index of
    0: bgBrush.Color := TAlphaColors.lightBlue;
    1: bgBrush.Color := TAlphaColors.MoneyGreen;
  end;
  Canvas.FillRect(Bounds, 0, 0, [], 1, bgBrush);

And finally an example of background color determined by value of data

  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);

And a sample image:

enter image description here

The texts are colored as in this answer

Community
  • 1
  • 1
Tom Brunberg
  • 20,312
  • 8
  • 37
  • 54
  • Thanks for a great expanded answer! – Ashlar Apr 28 '17 at 23:41
  • I tested out your answer in a project and found that the FillRect is hiding the text values. If I select the cell for editing, the data is there, but it disappears as soon as I change focus to another cell. The hide effect is applied to all columns whether color shaded or not. – Ashlar Apr 30 '17 at 21:48
  • When you use the `OnDrawColumnCell()` event you need to arrange drawing of background color first and then the text, IOW `FillRect()` first and `FillText()` after. – Tom Brunberg Apr 30 '17 at 22:16
  • Unfortunately,this is in a drawcolumncell method call. I don't think I know which cell is calling it at any time, what other parameter apply to the specific call, nor what text to place in it. Should I ask another question? – Ashlar May 01 '17 at 02:22
  • Why do you say *Unfortunately, ...*, we are both speaking about e.g. `procedure TForm11.Grid1DrawColumnCell()`, are we not? When I say `OnDrawColumnCell` I'm talking about the property, to which the IDE assigns the procedure name `Grid1DrawColumnCell`. If this is not clear, you need to ask a new question about that specifically, but first read the docs. At the end of my answer above, is a link to my answer on a q. regarding color of the text, which shows usage of the `FillText()` method. – Tom Brunberg May 01 '17 at 04:16
  • So I repeat, when you take control of rendering `TGrid` cell content using the `OnDrawColumnCell` event, you first call `FillRect()` to draw the background and then `FillText()` to draw the text. Both are methods of the `Canvas`. If this doesn't work for you, you may ask a new question, but include minimal, but complete code of what you try to do. – Tom Brunberg May 01 '17 at 04:16
  • I just came to think of it, maybe you are missing the `OnGetValue` and `OnSetValue` event handlers in your `TGrid`. Those are needed to store the values that you write into the cells and to fetch the values for display in the grid. If that is the case, search this site for `[delphi] OnGetValue` – Tom Brunberg May 01 '17 at 04:59
2

Please see this example. Explanations in comments:

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;
Sergey Zubkov
  • 115
  • 2
  • 10