2016-10-13 1 views
0

TStringGrid의 셀을 클릭하면 색상이 바뀌는 앱을 만들려고합니다. 셀을 클릭 할 때마다 다음 셀로 넘어가 다음 셀을 다시 클릭 할 때까지 다음 색상으로 전환해야합니다.Delphi 7 : StringGrid에서 개별 셀의 색상을 클릭하여 변경하려면 어떻게해야합니까?

흰색 ==> 빨간색 ==> 주황색 ==> 녹색 = => 흰색 (신호 등).

내가 겪고있는 오류 (들)은 설명하기가 조금 어렵지만 시도하겠습니다.

응용 프로그램이 실행되지만 하나의 셀을 클릭 한 다음 다른 셀을 클릭하면 때로는 클릭 한 첫 번째 셀에서 색상이 변경되지만 두 번째 셀에서는 변경되지 않습니다. 다른 때에는 두 셀 모두 색상이 바뀝니다. 다른 때에는 두 셀이 모두 흰색 상태로 재설정됩니다.

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 컨트롤은 여러 가지 이유로 자주 그려지기 때문에 모든 그리기 이벤트는 현재 그려져있는 특정 항목에 대해 현재 상태 만 페인팅해야합니다. OnSelectCell 또는 OnClick 이벤트를 사용하여 상태 시스템을 업데이트 한 다음 업데이트 된 셀의 다시 칠하기를 트리거해야합니다.

이 시도 : 또는

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

관련 문제