2016-08-16 5 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 Berlin - если это имеет значение.

Чтобы проверить это, я начал новый проект, добавил TGridPanel, установил его, чтобы иметь 1 строку и 5 одинаково разветвленных столбцов. Я добавил 6 TButton управления и создал OnClick обработчик для каждого с помощью следующего кода:

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

Нажмите несколько кнопок, чтобы добавить несколько панелей, а затем нажмите на панели, чтобы удалить их.

+5

Это никогда не может быть безопасным для вызова 'Free()' в 'Sender' события, пока вы все еще находитесь внутри обработчика событий. 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; 

Затем добавьте r и c переменные для строки и седловину, добавьте вызов 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 будет убит. С уважением, –

 Смежные вопросы

  • Нет связанных вопросов^_^