2016-08-16 44 views
3

我正在使用TGridPanel來保存一些面板。在設計時,我已將網格面板設置爲1行5列。獲取TGridPanel中單擊的控件的列索引

我可以添加使用此代碼面板到電網,效果很好:

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; 

我想要做的就是從網格中刪除一個TPanel當我點擊它(這就是爲什麼我有在上面的代碼中將點擊處理程序設置爲網格面板的點擊處理程序)。

在此點擊處理我這樣做,幾乎工程:

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; 

使用參數UpdateControlColumn()引起網格面板改變的順序 - 第一和第二交換位置。

我可以通過添加列idex到面板的標籤屬性,然後將其傳遞給UpdateControlColumn()來解決此問題。然後這就可以工作了,但是一旦面板被移除,較高的標籤號不再有效 - 面板移動了列。

那麼,如何從OnClick處理程序中獲取面板所在的列?

我使用Delphi 10.1柏林 - 如果這有什麼區別。

爲了測試這個,我開始了一個新項目,增加了一個TGridPanel,設置它有1行和5個等寬的列。我加了6所TButton控制,創造了每一個用下面的代碼的OnClick處理程序:

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

點擊幾個按鈕來添加一些面板,然後單擊面板將其刪除。

+5

當你仍然在事件處理程序中時,它從未**可安全地調用事件的'Sender'上的'Free()'。在事件處理程序退出後,RTL仍然需要訪問該對象。如果你需要釋放發件人,你必須*延遲免費,直到處理程序退出。通常我通過使用PostMessage()來將自己的自定義窗口消息與「LParam」中的對象指針一起發佈,然後讓消息處理程序在安全的情況下釋放該對象。這與'TForm'使用'CM_RELEASE'在'OnClose'事件處理程序返回'Action = caFree'時如何釋放自己相似' –

+0

謝謝@RemyLebeau,如果我繼續使用這種方法,我會整合你的建議。親切的問候, –

回答

1

TCustomGridPanel有一對有用的功能,CellIndexToCell()CellToCellIndex,但它們不公開,因此不能直接從TGridPanel訪問。

爲了讓下面這些可用的聲明TGridPanel重新:

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

然後加入rc變量ROW和COL,呼叫添加到CellIndexToCell()和使用c作爲論據UpdateControlsColumn

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; 

並按照關於釋放面板的Remy Lebeau的建議。 (我只注意到他的評論)。


如果您還沒有準備好,你可能還需要看看TFlowPanel及其FlowStyle財產。 TflowPanel刪除後重新排序更具可預測性,如果您使用多行,但當然取決於您需要什麼。

+0

謝謝@TomBrunberg - 非常感謝。我需要的是一排最多5個面板 - 不需要流動或調整大小,所以TFlowPanel將會被殺死。親切的問候, –

相關問題