2016-10-13 46 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

相關問題