2016-10-13 662 views
0

我想制作一个应用程序,其中TStringGrid的单元格在我点击它们时会改变颜色。每次我点击一个细胞,它应该切换到下一个颜色,并保持该颜色,直到我上单击单元格,依次是:Delphi 7:如何通过单击它们来更改StringGrid上的单个单元格的颜色?

白色==>红==>橙==>绿色= =>白色(如红绿灯)。

我正的错误(S)是有点难以解释,但我会尽力。

应用程序运行,但是当我点击一个单元格,然后在另一个,有时第一单元我点击改变颜色,但第二个没有。其他时候,两个细胞都会改变颜色。其他时候,两个单元都重置为白色状态。

type 
    TForm1 = class(TForm) 
    StringGrid: TStringGrid; 
    procedure StringGridDrawCell(Sender: TObject; ACol, ARow: Integer; 
     Rect: TRect; State: TGridDrawState); 
    private 
    arrState: array[1..4, 1..4] of Integer; 
end; 

procedure TForm1.StringGridDrawCell(Sender: TObject; ACol, ARow: Integer; 
    Rect: TRect; State: TGridDrawState); 
var 
    iRow, iCol: Integer; 
    arrk: array[1..4, 1..4] of Integer; 
begin 
    for iCol := 4 downto 1 do 
    begin 
    for iRow := 4 downto 1 do 
    begin 
     if (gdSelected in State) then 
     begin 
     case arrState[ARow, aCol] of 
      0: begin 
      StringGrid.Canvas.Brush.Color := clWhite; 
      Rect := StringGrid.CellRect(iCol, iRow); 
      StringGrid.Canvas.FillRect(Rect); 
      Inc(arrState[iRow, iCol]); 
      end; 

      1: begin 
      StringGrid.Canvas.Brush.Color := clRed; 
      Rect := StringGrid.CellRect(iCol, iRow); 
      StringGrid.Canvas.FillRect(Rect); 
      Inc(arrState[iRow, iCol]); 
      end; 

      2: begin 
      StringGrid.Canvas.Brush.Color := $008CFF; 
      Rect := StringGrid.CellRect(iCol, iRow); 
      StringGrid.Canvas.FillRect(Rect); 
      Inc(arrState[iRow, iCol]); 
      end; 

      3: begin 
      StringGrid.Canvas.Brush.Color := clGreen; 
      Rect := StringGrid.CellRect(iCol, iRow); 
      StringGrid.Canvas.FillRect(Rect); 
      arrState[iRow, iCol] := 0; 
      end; 

     end; 
     end; 
    end; 
    end; 
end; 

回答

3

问题是您正在使用OnDrawCell事件来更新状态机。切勿使用绘图事件来驱动状态更改!一个UI控件经常被绘制并且出于很多原因,所以任何绘图事件都应该绘制当前正在绘制的特定项目的当前状态。您应该使用OnSelectCellOnClick事件来更新状态机,然后触发重新刷新更新的单元。

试试这个:

type 
    TForm1 = class(TForm) 
    StringGrid: TStringGrid; 
    procedure StringGridDrawCell(Sender: TObject; ACol, ARow: Integer; 
     Rect: TRect; State: TGridDrawState); 
    procedure StringGridSelectCell(Sender: TObject; ACol, ARow: Integer; 
     var CanSelect: Boolean); 
    private 
    arrState: array[1..4, 1..4] of Integer; 
end; 

procedure TForm1.StringGridDrawCell(Sender: TObject; ACol, ARow: Integer; 
    Rect: TRect; State: TGridDrawState); 
const 
    clOrange = TColor($008CFF); 
    CellColors: array[0..3] of TColor = (clWhite, clRed, clOrange, clGreen); 
begin 
    if (ACol in [1..4]) and (ARow in [1..4]) then 
    begin 
    StringGrid.Canvas.Brush.Color := CellColors[arrState[ARow, ACol]]; 
    StringGrid.Canvas.FillRect(Rect); 
    end; 
end; 

// TStringGrid.InvalidateCell() is protected, 
// but can be reached using an accessor class.. 
type 
    TStringGridAccess = class(TStringGrid) 
    end; 

procedure TForm1.StringGridSelectCell(Sender: TObject; ACol, ARow: Integer; 
    var CanSelect: Boolean); 
begin 
    if (ACol in [1..4]) and (ARow in [1..4]) then 
    begin 
    arrState[ARow, ACol] := (arrState[ARow, ACol] + 1) mod 4; 
    TStringGridAccess(StringGrid).InvalidateCell(ACol, ARow); 
    end; 
end; 

或者:

type 
    TForm1 = class(TForm) 
    StringGrid: TStringGrid; 
    procedure StringGridClick(Sender: TObject); 
    procedure StringGridDrawCell(Sender: TObject; ACol, ARow: Integer; 
     Rect: TRect; State: TGridDrawState); 
    private 
    arrState: array[1..4, 1..4] of Integer; 
    end; 

// TStringGrid.InvalidateCell() is protected, 
// but can be reached using an accessor class.. 
type 
    TStringGridAccess = class(TStringGrid) 
    end; 

procedure TForm1.StringGridClick(Sender: TObject); 
type 
    POINTS = packed record 
    x: SHORT; 
    y: SHORT; 
    end; 
var 
    dwPos: DWORD; 
    pts: POINTS absolute dwPos; 
    pt: TPoint; 
    iCol, iRow: Integer; 
begin 
    dwPos := GetMessagePos(); 
    pt := StringGrid.ScreenToClient(Point(pts.x, pts.y)); 
    StringGrid.MouseToCell(pt.X, pt.Y, iCol, iRow); 
    if (iCol in [1..4]) and (iRow in [1..4]) then 
    begin 
    arrState[iRow, iCol] := (arrState[iRow, iCol] + 1) mod 4; 
    TStringGridAccess(StringGrid).InvalidateCell(iCol, iRow); 
    end; 
end; 

procedure TForm1.StringGridDrawCell(Sender: TObject; ACol, ARow: Integer; 
    Rect: TRect; State: TGridDrawState); 
const 
    clOrange = TColor($008CFF); 
    CellColors: array[0..3] of TColor = (clWhite, clRed, clOrange, clGreen); 
begin 
    if (ACol in [1..4]) and (ARow in [1..4]) then 
    begin 
    StringGrid.Canvas.Brush.Color := CellColors[arrState[ARow, ACol]]; 
    StringGrid.Canvas.FillRect(Rect); 
    end; 
end; 
+0

谢谢你这么多! – Ragglepop

相关问题