2012-01-15 11 views
6

Io e 2 persone abbiamo cercato di capire quale dovrebbe essere una formula semplice. Ho una griglia, che può avere un numero variabile di colonne e righe. Quando l'utente fa clic su una delle celle, devo determinare quale 'indice' è stato cliccato in base a colonna/riga. Gli indici iniziano da 0 e vanno da sinistra a destra, quindi dall'alto verso il basso. Non ci sono colonne/righe fisse.Matematica per determinare l'indice delle voci in base alla selezione di colonne/righe nella griglia

Esempio di ciò che intendo: enter image description here

Quindi, se ci sono 3 colonne, e l'utente clicca sul C2/R1, quindi ha bisogno di risolvere l'indice di 5. Tutti gli indici partono da 0 in questo esempio .

La mia formula attuale, che è lontano dal lavoro, è come questo:

//I = Calculated index based on row/col (starts from 0) 
//ACol = Column index user clicked (starts from 0) 
//ARow = Row index user clicked (starts from 0) 
//ColCount = Number of columns 

I:= (C * ColCount) + (R - ColCount); 

EDIT

Per riferimento, qui è tutta la mia unità componente di seguito.

La linea con la formula è contrassegnato con un commento "FORMULA QUI"

unit ImageGrid; 

interface 

uses 
    Windows, Classes, SysUtils, Grids, Graphics, StdCtrls, ExtCtrls, Controls, 
    Jpeg, PngImage; 

type 
    TImageGrid = class; 
    TImageGridItem = class; 

    TGridSizing = (gsManual, gsAuto, gsFit); 

    TImageGridItem = class(TObject) 
    private 
    FFilename: TFilename; 
    FOwner: TImageGrid; 
    FBmp: TBitmap; 
    procedure Event; 
    procedure SetFilename(const Value: TFilename); 
    public 
    constructor Create(AOwner: TImageGrid); 
    destructor Destroy; override; 
    procedure LoadFile; 
    published 
    property Filename: TFilename read FFilename write SetFilename; 
    end; 

    TImageGrid = class(TCustomDrawGrid) 
    private 
    FItems: TStringList; 
    FCacheDir: String; 
    FRowHeight: Integer; 
    FColWidth: Integer; 
    FSizing: TGridSizing; 
    FItemIndex: Integer; 
    procedure SetCacheDir(const Value: String); 
    procedure SetColWidth(const Value: Integer); 
    procedure SetRowHeight(const Value: Integer); 
    procedure SetSizing(const Value: TGridSizing); 
    function GetItem(Index: Integer): TImageGridItem; 
    procedure SetItem(Index: Integer; const Value: TImageGridItem); 
    procedure SetItemIndex(const Value: Integer); 
    procedure SelectCell(Sender: TObject; ACol, ARow: Longint; 
     var CanSelect: Boolean); 
    protected 
    procedure Paint; override; 
    public 
    constructor Create(AOwner: TComponent); override; 
    destructor Destroy; override; 
    function Count: Integer; 
    property Items[Index: Integer]: TImageGridItem 
     read GetItem write SetItem; default; 
    function Add: TImageGridItem; 
    procedure Delete(const Index: Integer); 
    procedure Clear; 
    published 
    property CacheDir: String read FCacheDir write SetCacheDir; 
    property ColWidth: Integer read FColWidth write SetColWidth; 
    property RowHeight: Integer read FRowHeight write SetRowHeight; 
    property Sizing: TGridSizing read FSizing write SetSizing; 
    property ItemIndex: Integer read FItemIndex write SetItemIndex; 

    property Align; 
    property Anchors; 
    property BevelEdges; 
    property BevelInner; 
    property BevelKind; 
    property BevelOuter; 
    property BevelWidth; 
    property BiDiMode; 
    property BorderStyle; 
    property Color; 
    property ColCount; 
    property Constraints; 
    property Ctl3D; 
    property DefaultColWidth; 
    property DefaultRowHeight; 
    property DefaultDrawing; 
    property DoubleBuffered; 
    property DragCursor; 
    property DragKind; 
    property DragMode; 
    property DrawingStyle; 
    property Enabled; 
    property Font; 
    property GradientEndColor; 
    property GradientStartColor; 
    property GridLineWidth; 
    property Options; 
    property ParentBiDiMode; 
    property ParentColor; 
    property ParentCtl3D; 
    property ParentDoubleBuffered; 
    property ParentFont; 
    property ParentShowHint; 
    property PopupMenu; 
    property ScrollBars; 
    property ShowHint; 
    property TabOrder; 
    property Touch; 
    property Visible; 

    property OnClick; 
    property OnColumnMoved; 
    property OnContextPopup; 
    property OnDblClick; 
    property OnDragDrop; 
    property OnDragOver; 
    property OnDrawCell; 
    property OnEndDock; 
    property OnEndDrag; 
    property OnEnter; 
    property OnExit; 
    property OnGesture; 
    property OnGetEditMask; 
    property OnGetEditText; 
    property OnKeyDown; 
    property OnKeyPress; 
    property OnKeyUp; 
    property OnMouseActivate; 
    property OnMouseDown; 
    property OnMouseEnter; 
    property OnMouseLeave; 
    property OnMouseMove; 
    property OnMouseUp; 
    property OnMouseWheelDown; 
    property OnMouseWheelUp; 
    property OnRowMoved; 
    property OnSelectCell; 
    property OnSetEditText; 
    property OnStartDock; 
    property OnStartDrag; 
    property OnTopLeftChanged; 
    end; 

implementation 

//Register procedure will come later... 

{ TImageGrid } 

function TImageGrid.Add: TImageGridItem; 
begin 
    Result:= TImageGridItem.Create(Self); 
    FItems.AddObject('', Result); 
end; 

procedure TImageGrid.Clear; 
begin 
    while Count > 0 do 
    Delete(0); 
end; 

function TImageGrid.Count: Integer; 
begin 
    Result:= FItems.Count; 
end; 

constructor TImageGrid.Create(AOwner: TComponent); 
begin 
    inherited; 
    Options:= [goFixedVertLine,goFixedHorzLine,goVertLine,goHorzLine, 
    goRangeSelect,goThumbTracking]; 
    Parent:= TWinControl(AOwner); 
    FItems:= TStringList.Create; 
    FixedCols:= 0; 
    FixedRows:= 0; 
    RowCount:= 1; 
    ColCount:= 1; 
    FColWidth:= 100; 
    FRowHeight:= 100; 
    ColWidths[0]:= FColWidth; 
    RowHeights[0]:= FRowHeight; 
    FSizing:= gsManual; 
    FItemIndex:= -1; 
    OnSelectCell:= SelectCell; 

    Invalidate; 
end; 

procedure TImageGrid.Delete(const Index: Integer); 
begin 
    if (Index >= 0) and (Index < FItems.Count) then begin 
    TImageGridItem(FItems.Objects[Index]).Free; 
    FItems.Delete(Index); 
    end else begin 
    raise Exception.Create('List index out of bounds ('+IntToStr(Index)+')'); 
    end; 
end; 

destructor TImageGrid.Destroy; 
begin 
    FItems.Free; 
    inherited; 
end; 

function TImageGrid.GetItem(Index: Integer): TImageGridItem; 
begin 
    if (Index >= 0) and (Index < FItems.Count) then begin 
    Result:= TImageGridItem(FItems.Objects[Index]); 
    end else begin 
    Result:= nil; 
    raise Exception.Create('List index out of bounds ('+IntToStr(Index)+')'); 
    end; 
end; 

procedure TImageGrid.Paint; 
var 
    Bmp: TBitmap; 
    C: Integer; 
    RC: Integer; 
    CC: Integer; 
    X, Y: Integer; 
    I: TImageGridItem; 
    R: TRect; 

    procedure DrawImage(B: TBitmap; const R: TRect); 
    begin 
    Canvas.StretchDraw(R, B); 
    end; 

begin 
    Canvas.Brush.Style:= bsSolid; 
    Canvas.Pen.Style:= psClear; 
    Canvas.Brush.Color:= clWhite; 
    Canvas.FillRect(Canvas.ClipRect); 
    Bmp:= TBitmap.Create; 
    try 
    if Count > 0 then begin 
     case FSizing of 
     gsManual: begin 
      //Draw like regular grid with variable sizes - expand rows as needed 
      inherited; 

     end; 
     gsAuto: begin 
      //Calculate image width based on col count 

     end; 
     gsFit: begin 
      //Calculate col count based on image width 
      CC:= Trunc(ClientWidth/FColWidth); 
      RC:= Trunc(Count/CC); 
      ColCount:= CC; 
      RowCount:= RC; 
      for X := 0 to ColCount - 1 do 
      ColWidths[X]:= FColWidth; 
      for X := 0 to RowCount - 1 do 
      RowHeights[X]:= FRowHeight; 
      Canvas.Brush.Style:= bsSolid; 
      Canvas.Pen.Style:= psSolid; 
      Canvas.Brush.Color:= clWhite; 
      Canvas.Pen.Width:= 1; 
      C:= 0; //C = Count of items to show 
      for X := 0 to ColCount - 1 do begin 
      for Y := 0 to RowCount - 1 do begin 
       I:= Self.Items[C]; 
       if C = FItemIndex then begin 
       Canvas.Pen.Color:= clRed; 
       Canvas.Pen.Width:= 2; 
       end else begin 
       Canvas.Pen.Color:= clNavy; 
       Canvas.Pen.Width:= 1; 
       end; 
       R:= CellRect(X,Y); 
       Canvas.Rectangle(R); 
       InflateRect(R, -4, -4); 
       Canvas.StretchDraw(R, I.FBmp); 
       C:= C + 1; 
      end; 
      end; 
     end; 
     end; 
    end else begin 
     ColCount:= 1; 
     RowCount:= 1; 
    end; 
    finally 
    Bmp.Free; 
    end; 
end; 

procedure TImageGrid.SelectCell(Sender: TObject; ACol, ARow: Integer; 
    var CanSelect: Boolean); 
var 
    I: Integer; 
    C, R: Integer; 
begin 
    //Determine item index based on col/row 

    C:= ACol; 
    R:= ARow; 

    //I = Calculated index based on row/col (starts from 0) 
    //ACol = Column index user clicked (starts from 0) 
    //ARow = Row index user clicked (starts from 0) 
    //ColCount = Number of columns 

    I:= (R * ColCount) + C; //  <<----- FORMULA HERE 

    if I < Count - 1 then begin 
    FItemIndex:= I; 
    CanSelect:= True; 
    end else begin 
    FItemIndex:= -1; 
    CanSelect:= False; 
    end; 
    Invalidate; 
end; 

procedure TImageGrid.SetCacheDir(const Value: String); 
begin 
    if Value <> FCacheDir then begin 
    FCacheDir := Value; 
    Invalidate; 
    end; 
end; 

procedure TImageGrid.SetColWidth(const Value: Integer); 
begin 
    if Value <> FColWidth then begin 
    FColWidth := Value; 
    Invalidate; 
    end; 
end; 

procedure TImageGrid.SetItem(Index: Integer; const Value: TImageGridItem); 
begin 
    if (Index >= 0) and (Index < FItems.Count) then begin 
    FItems.Objects[Index]:= Value; 
    Invalidate; 
    end else begin 
    raise Exception.Create('List index out of bounds ('+IntToStr(Index)+')'); 
    end; 
end; 

procedure TImageGrid.SetItemIndex(const Value: Integer); 
begin 
    if Value <> FItemIndex then begin 
    FItemIndex := Value; 
    Invalidate; 
    end; 
end; 

procedure TImageGrid.SetRowHeight(const Value: Integer); 
begin 
    if Value <> FRowHeight then begin 
    FRowHeight := Value; 
    Invalidate; 
    end; 
end; 

procedure TImageGrid.SetSizing(const Value: TGridSizing); 
begin 
    if Value <> FSizing then begin 
    FSizing := Value; 
    Invalidate; 
    end; 
end; 

{ TImageGridItem } 

constructor TImageGridItem.Create(AOwner: TImageGrid); 
begin 
    FOwner:= AOwner; 
    FBmp:= TBitmap.Create; 
end; 

destructor TImageGridItem.Destroy; 
begin 
    FBmp.Free; 
    inherited; 
end; 

procedure TImageGridItem.Event; 
begin 
    FOwner.Invalidate; 
end; 

procedure TImageGridItem.LoadFile; 
    //Determine file type and load accordingly 
    function GetImage(const Filename: String; B: TBitmap): Bool; 
    var 
    E: String; 
    IJ: TJpegImage; 
    IP: TPngObject; 
    begin 
    Result:= False; 
    if FileExists(Filename) then begin 
     E:= UpperCase(ExtractFileExt(Filename)); 
     if E = '.BMP' then begin 
     B.LoadFromFile(Filename); 
     Result:= True; 
     end else 
     if (E = '.JPG') or (E = '.JPEG') then begin 
     IJ:= TJpegImage.Create; 
     try 
      IJ.LoadFromFile(Filename); 
      B.Assign(IJ); 
      Result:= True; 
     finally 
      IJ.Free; 
     end; 
     end else 
     if E = '.PNG' then begin 
     IP:= TPngObject.Create; 
     try 
      IP.LoadFromFile(Filename); 
      B.Assign(IP); 
      Result:= True; 
     finally 
      IP.Free; 
     end; 
     end else begin 
     raise Exception.Create('Invalid file extension ('+E+')'); 
     end; 
    end; 
    end; 

begin 
    GetImage(FFilename, FBmp); 
end; 

procedure TImageGridItem.SetFilename(const Value: TFilename); 
begin 
    if Value <> FFilename then begin 
    FFilename := Value; 
    LoadFile; 
    Event; 
    end; 
end; 

end. 

RISOLTO

Grazie alla risposta qui sotto, ho capito riparato. All'inizio pensavo che la formula fosse sbagliata, ma dopo aver esaminato più del mio codice, ho scoperto che in un altro punto, era in loop scorretto tra le righe e le colonne. Qui di seguito è come dovrebbe funzionare ...

for Y := 0 to RowCount - 1 do begin 
    for X := 0 to ColCount - 1 do begin 

Ma quello che avevo prima era ...

for X := 0 to ColCount - 1 do begin 
    for Y := 0 to RowCount - 1 do begin 
+2

ne dite '(R * ColCount) + C'? –

+5

E riguardo '(ARow * ColCount) + ACol'? @ Leneven, tu leggi la mia mente; eri più veloce, la risposta è tua :) – TLama

+5

@TLama - Il mio segreto è fuori. Ora tutti sanno che non riesco a trovare una risposta io stesso :) –

risposta

16

seguito dovrebbe fare il trucco

(R * ColCount) + C 

Per i vostri esempi, questo sarebbe diventa

(2 * 3) + 2 = 8 

e ... se ci sono 3 colonne, e l'utente fa clic su C2/R1, quindi ha bisogno di risolvere l'indice del 5

(1 * 3) + 2 = 5 
+1

@Lieven: lo attribuirò a George allora. Grazie per aver risposto e cercando di trovare il giusto George! –

+0

Non sembra funzionare ... Mi prenderò il tempo di spiegare come non ha funzionato in un po ', non abbastanza tempo al momento ... –

+1

GOT IT. Errore stupido La tua formula era perfetta, grazie. Ma nella mia procedura di pittura, stavo scorrendo in modo errato tra le righe/colonne. Lo ha cambiato e funziona: D –

Problemi correlati