Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Komplizierte StringGrid-Frage (https://www.delphipraxis.net/148315-komplizierte-stringgrid-frage.html)

Talia 27. Feb 2010 13:58


Komplizierte StringGrid-Frage
 
Hallo, Delphi-Spezialisten! :balloon:

Ich habe auf einem Formular 6 StringGrids A und 6 StringGrids B jeweils in einem array[1..6] of TStringGrid abgelegt. Außerdem gibt es noch einen nArray[1..6] of Integer und einen array [1..6] of TSet.

SGA[1], SGB[1], nArray[1] und Set[1] gehören zusammen und enthalten Informationen, die sie untereinander austauschen sollen.

Die SGA[i] haben ein StringGridASelectCell-Ereignis, auf das sie alle zugreifen (Im Objectinspector so eingestellt).


Hier mal etwas code:

Delphi-Quellcode:
procedure TForm1.StringGridASelectCell(Sender: TObject; ACol, ARow: Integer;
  var CanSelect: Boolean);
begin
  with Sender as TStringGrid do
  begin
    Objects[ACol, ARow] := TObject(not Boolean(Objects[ACol, ARow]));
    if Boolean(Objects[ACol, ARow]) then
      if nArray[(Sender as TStringGrid).Tag] < 6 then
      begin
        Inc(nArray[(Sender as TStringGrid).Tag]);
        ...
        Include(SetArray[(Sender as TStringGrid).Tag], ...);
        ...
      end
"Kennt" das angeklickte StrinGGrid seine Position im SGArray? Die würde ich jetzt nämlich brauchen. Wie man sieht habe ich mir so geholfen, daß ich die SGA von 1 bis 6 getaggt habe, lieber wäre mir aber eine "richtige" Lösung

DeddyH 27. Feb 2010 14:06

Re: Komplizierte StringGrid-Frage
 
Ich denke, für die zusammengehörigen Objekte dürfte sich eine Manager-Klasse anbieten, die man ihnen "überstülpt". Über diese Klasse können sie untereinander bekannt gemacht werden. Anschließend brauchst Du dann nur noch ein Array, nämlich eins mit Elementen dieser Klasse.

Talia 1. Mär 2010 17:58

Re: Komplizierte StringGrid-Frage
 
Hätte ich mir ja gleich denken können: Am besten funktioniert's, wenn man vorher richtig plant!! :wink:

Gruß Talia

DeddyH 1. Mär 2010 18:03

Re: Komplizierte StringGrid-Frage
 
So isses ;)

Talia 3. Mär 2010 11:55

Re: Komplizierte StringGrid-Frage
 
Hallo, nochmal!

Ich habe jetzt meine StringGrids, Integer und Set in einem record zusammengefasst und dann einen InfoFeld: array[1..6] of TInfoFeld erstellt. Dadurch werden viele Stellen besser lesbar, aber für das SelectCell-Ereignis habe ich immer noch keine richtige Lösung, nur einen neuen Workaround:

Code:
procedure TForm1.StringGridASelectCell(Sender: TObject; ACol, ARow: Integer;
  var CanSelect: Boolean);
var
  n, i: Integer;
begin
  with Sender as TStringGrid do
    for i := 1 to 6 do
      if InfoFeld[i].StringGridA = TStringGrid(Sender) then
      begin
        n := i;
        Objects[ACol, ARow] := TObject(not Boolean(Objects[ACol, ARow]));
        if Boolean(Objects[ACol, ARow]) then
          if InfoFeld[n].Anzahl < 6 then
          begin
            Inc(InfoFeld[n].Anzahl);
            ...
            Include(InfoFeld[n].ElementeSet, ...);
            ...
          end
Die Position des SGA im Array wird also getestet. Gibt es einen direkten Zugriff auf den Namen des auslösenden StringGrids? Wenn nicht, wie mache ich die denn "bekannt"?

DeddyH 3. Mär 2010 12:34

Re: Komplizierte StringGrid-Frage
 
Ich hatte eigentlich von einer Klasse gesprochen und nicht von einem Record. Im Moment habe ich keine Zeit, ein Beispiel zu schreiben, aber nach 14:30 kann ich das gern einmal tun.

[edit] So, hier nun ein Beispiel, wie ich mir das so gedacht hatte (ein Formular mit 3 Edits und 3 CheckBoxen):
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  //Forward-Deklaration der Containerklasse
  TMyContainer = class;

  //Ableitung von der Standard-Checkbox mit zusätzlicher Property
  TCheckBox = class(StdCtrls.TCheckBox)
  private
    FContainer: TMyContainer;
  public
    property Container: TMyContainer read FContainer write FContainer;
  end;

  //Ableitung vom Standard-Edit mit zusätzlicher Property
  TEdit = class(StdCtrls.TEdit)
  private
    FContainer: TMyContainer;
  public
    property Container: TMyContainer read FContainer write FContainer;
  end;

  //eigene Container-Klasse mit einer Checkbox, einem Edit sowie Demo-Zusatzdaten
  TMyContainer = class
  private
    FCheckbox: TCheckbox;
    FEdit: TEdit;
    FIntFeld: integer;
    procedure CheckBoxClick(Sender: TObject);
  public
    constructor Create(aCheckbox: TCheckbox;aEdit: TEdit);
    property Checkbox: TCheckBox read FCheckBox;
    property Edit: TEdit read FEdit;
    property IntFeld: integer read FIntFeld write FIntFeld;
  end;

  TForm1 = class(TForm)
    CheckBox1: TCheckBox;
    Edit1: TEdit;
    CheckBox2: TCheckBox;
    Edit2: TEdit;
    CheckBox3: TCheckBox;
    Edit3: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private-Deklarationen }
    FArray: array of TMyContainer;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TMyContainer }

constructor TMyContainer.Create(aCheckbox: TCheckbox; aEdit: TEdit);
begin
  inherited Create;
  //Referenzen wechselseitig zuweisen
  FCheckBox := aCheckBox;
  FEdit := aEdit;
  if Assigned(FCheckBox) then
    begin
      FCheckBox.Container := self;
      FCheckBox.OnClick := CheckBoxClick;
    end;
  if Assigned(FEdit) then
    FEdit.Container := self;
end;

procedure TMyContainer.CheckBoxClick(Sender: TObject);
const Choices: array[Boolean] of String = ('ist nicht gechecked','ist gechecked');
var Edit: TEdit;
begin
  //zur Demonstration aus der Checkbox auf das zugehörige Edit zugreifen
  if Sender is TCheckBox then
    if Assigned(TCheckBox(Sender).Container) then
      begin
        Edit := TCheckBox(Sender).Container.Edit;
        if Assigned(Edit) then
          Edit.Text := Format('%s (%d) %s.',[TCheckBox(Sender).Name,
                                             TCheckBox(Sender).Container.IntFeld,
                                             Choices[TCheckBox(Sender).Checked]]);
      end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
  SetLength(FArray,3);
  FArray[0] := TMyContainer.Create(CheckBox1, Edit1);
  FArray[0].IntFeld := Random(100);
  FArray[1] := TMyContainer.Create(CheckBox2, Edit2);
  FArray[1].IntFeld := Random(100);
  FArray[2] := TMyContainer.Create(CheckBox3, Edit3);
  FArray[2].IntFeld := Random(100);
end;

procedure TForm1.FormDestroy(Sender: TObject);
var i: integer;
begin
  for i := High(FArray) downto Low(FArray) do
    FArray[i].Free;
  //hatte ich vergessen
  SetLength(FArray,0);
end;

end.

Talia 3. Mär 2010 18:09

Re: Komplizierte StringGrid-Frage
 
Vielen Dank für Deine Mühe!!
Das wechselseitige Zuweisen der Referenzen sehe ich zum ersten Mal. Ich bin wirklich ein Noob. Die Unit bekommt einen Ehrenplatz unter meinen Vorlagen. :love:

Gruß Talia


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:10 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz