2016-08-16 5 views
3

Ich bin mit einem TGridPanel einige Platten zu halten. Zur Entwurfszeit habe ich das Rasterfeld auf 1 Zeile und 5 Spalten eingestellt.Erster Spaltenindex einer geklickt Kontrolle in TGridPanel

ich ein Panel zu dem Gitter hinzufügen, kann diesen Code verwenden, die gut funktioniert:

procedure TForm6.AddPanelToGrid(const ACaption: string); 
var 
    pnl: TPanel; 
begin 
    pnl := TPanel.Create(gpOne); 
    pnl.Caption := ACaption; 
    pnl.Parent := gpOne; 
    pnl.Name := 'pnlName' + ACaption; 
    pnl.OnClick := gpOne.OnClick; 
    pnl.ParentBackground := false; 
    pnl.ParentColor := false; 
    pnl.Color := clLime; 
    pnl.Font.Size := 14; 
    gpOne.ControlCollection.AddControl(pnl); 
    pnl.Height := pnl.Width; 
end; 

Was ich tun möchte, ist ein TPanel aus dem Netz zu entfernen, wenn ich darauf klicke (was, warum ich habe Setzen Sie den On-Click-Handler auf den des Grid-Panels im obigen Code.

In diesen Click-Handler ich dies tun, die fast funktionieren:

procedure TForm6.gpOneClick(Sender: TObject); 
begin 
    if not (sender is TPanel) then exit; 

    gpOne.ControlCollection.RemoveControl(Sender as TPanel); 
    (Sender as TPanel).Free; 

    gpOne.UpdateControlsColumn(0); <<<------- 
    gpOne.UpdateControlsRow(0); 

    gpOne.Refresh(); 
end; 

einen Parameter für UpdateControlColumn() Verwendung bewirkt, dass die Reihenfolge der Platten im Netz zu ändern - die ersten und die zweiten Swap-Plätze. um diesen

ich durch Hinzufügen der Spalte idex auf den Panels Tag-Eigenschaft erhalten kann, dann ist das (auf UpdateControlColumn passieren). Dies funktioniert dann, aber sobald ein Panel entfernt wurde, sind die höheren Tag-Nummern nicht mehr gültig - die Panels haben die Spalte verschoben.

Also, wie kann ich die Spalte, die eine Platte in aus dem OnClick Handler ist?

Ich benutze Delphi 10.1 Berlin - wenn das einen Unterschied macht.

Um dies zu testen, habe ich ein neues Projekt gestartet, fügte eine TGridPanel hinzu, legte es auf 1 Zeile und 5 gleich Breite Spalten. Ich habe 6 TButton Kontrollen und erstellt ein OnClick Handler für jedes mit dem folgenden Code:

AddPanelToGrid('One'); // changing the string for each button. 

ein paar Knöpfe Klicken, um einige Platten hinzuzufügen, dann die Platten klicken, um sie zu entfernen.

+5

Es ist ** nie ** sicher, 'Free()' auf dem 'Sender' eines Ereignisses aufzurufen, während Sie sich noch im Ereignishandler befinden. Die RTL benötigt nach dem Beenden des Event-Handlers weiterhin Zugriff auf das Objekt. Wenn Sie den 'Sender' freigeben müssen, * müssen * Sie das Freimachen verzögern, bis der HF beendet ist.Normalerweise mache ich das, indem ich 'PostMessage()' benutze, um mir eine benutzerdefinierte Fensternachricht mit dem Objektzeiger in dem 'LParam' zu posten und dann den Nachrichtenhandler das Objekt freigeben zu lassen, wenn es sicher ist. Dies ist ähnlich wie 'TForm'' CM_RELEASE' verwendet, um sich selbst zu befreien, wenn sein 'OnClose' Ereignishandler' Action = caFree' zurückgibt. –

+0

Danke, @RemyLebeau, wenn ich mit dieser Methode fortfahre, werde ich Ihren Vorschlag einbeziehen. Herzliche Grüße, –

Antwort

1

TCustomGridPanel hat ein paar nützliche Funktionen, CellIndexToCell() und CellToCellIndex, aber sie sind nicht öffentlich und daher nicht direkt von einem TGridPanel zugänglich.

procedure TForm27.gpOneClick(Sender: TObject); 
var 
    r, c: integer; 
begin 
    if not (sender is TPanel) then exit; 

    gpOne.CellIndexToCell(gpOne.ControlCollection.IndexOf(Sender as TPanel), c, r); // add this 

    gpOne.ControlCollection.RemoveControl(Sender as TPanel); 
    (Sender as TPanel).Free; 

    gpOne.UpdateControlsColumn(c); // <<<------- 
    gpOne.UpdateControlsRow(0); 

    gpOne.Refresh(); 
end; 
:

Um sie zugänglich zu machen TGridPanel aufs Neue erklären, wie unten: für UpdateControlsColumn

type 
    TGridPanel = class(Vcl.ExtCtrls.TGridPanel) // add this 
    end;           // -"- 
    TForm27 = class(TForm) 
    Button1: TButton; 
    gpOne: TGridPanel; 
    ... 
    end; 

r und c Variablen für Zeile und Spalte Dann fügen Sie, um den Anruf zu CellIndexToCell() und c als Argument hinzufügen

Und folgen Sie Ratschläge von Remy Lebeau, in Bezug auf die Freigabe der Platte. (Ich habe gerade seinen Kommentar bemerkt).


Wenn Sie nicht bereits haben, können Sie auch einen Blick auf TFlowPanel und seine FlowStyle Eigentum zu nehmen. TflowPanel Neuordnung nach dem Löschen ist vorhersagbarer, wenn Sie mehr als eine Zeile verwenden, hängt aber natürlich davon ab, was Sie brauchen.

+0

Danke, @TomBrunberg - sehr geschätzt. Alles, was ich brauche, ist eine einzige Reihe von bis zu 5 Panels - kein Flowing oder Größenanpassung ist notwendig, also wäre FlowPanel zu viel zu töten. Mit freundlichen Grüßen, –

Verwandte Themen