#delphi #dynamic-controls
#delphi #динамические элементы управления
Вопрос:
У меня есть вопросы о том, как создавать динамические элементы управления, как уничтожать и как получать значение внутри вновь созданного элемента управления.
Создание и подсчет изменений создание в форме работало корректно, но там, где я создаю изменения в панелях с кнопками для уничтожения выбранной панели (панель [Редактировать, кнопка]), она создается правильно, но подсчет не работает.
И я не знаю, как уничтожить выбранную мной панель с помощью edit без ошибок (я еще не сделал этого в коде ниже).
У меня есть этот код:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;
type
TfrmMain = class(TForm)
btnCreateNewObject: TButton;
btnCountValues: TButton;
btnCreateNewPanels: TButton;
btnAllEditsInPanels: TButton;
procedure btnCreateNewObjectClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure btnCountValuesClick(Sender: TObject);
procedure btnCreateNewPanelsClick(Sender: TObject);
procedure btnAllEditsInPanelsClick(Sender: TObject);
private
dynEdit: TEdit;
dynPanel: TPanel;
yposition: integer;
ypositionpanel: integer;
{ Private declarations }
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
procedure TfrmMain.btnCountValuesClick(Sender: TObject);
var
i: integer;
res: integer;
begin
res := 0;
for i := 0 to Self.ControlCount - 1 do
begin
if Controls[i] is TEdit then
begin
res := res StrToInt((Controls[i] as TEdit).Text);
end;
end;
ShowMessage(IntToStr(res));
end;
procedure TfrmMain.btnCreateNewObjectClick(Sender: TObject);
begin
dynEdit := TEdit.Create(Self);
with dynEdit do
begin
Parent := frmMain;
Width := 80;
Height := 25;
Top := yposition;
Left := 3;
end;
yposition := yposition 26
end;
procedure TfrmMain.btnCreateNewPanelsClick(Sender: TObject);
begin
dynPanel := TPanel.Create(Self);
with dynPanel do
begin
Parent := frmMain;
Width := 100;
Height := 40;
Top := ypositionpanel;
Left := 120;
dynEdit := TEdit.Create(Self);
with dynEdit do
begin
Parent := dynPanel;
Width := 80;
Height := 25;
Top := 3;
Left := 3;
end;
end;
ypositionpanel := ypositionpanel 41;
end;
procedure TfrmMain.btnAllEditsInPanelsClick(Sender: TObject);
var
i, j: integer;
res: integer;
begin
res := 0;
for i := 0 to Self.ControlCount - 1 do
begin
for j := 0 to dynPanel.ControlCount - 1 do
begin
if dynPanel.Controls[j] is TEdit then
begin
res := res StrToInt( (Controls[j] as TEdit).Text );
end;
end;
end;
ShowMessage(IntToStr(res));
end;
procedure TfrmMain.FormCreate(Sender: TObject);
begin
yposition := 1;
ypositionpanel := 1;
end;
end.
object frmMain: TfrmMain
Left = 0
Top = 0
Caption = 'frmMain'
ClientHeight = 500
ClientWidth = 888
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object btnCreateNewObject: TButton
Left = 775
Top = 475
Width = 113
Height = 25
Caption = 'Create new edit'
TabOrder = 0
OnClick = btnCreateNewObjectClick
end
object btnCountValues: TButton
Left = 775
Top = 444
Width = 113
Height = 25
Caption = 'Count all edits'
TabOrder = 1
OnClick = btnCountValuesClick
end
object btnCreateNewPanels: TButton
Left = 648
Top = 475
Width = 121
Height = 25
Caption = 'Create new panels'
TabOrder = 2
OnClick = btnCreateNewPanelsClick
end
object btnAllEditsInPanels: TButton
Left = 648
Top = 444
Width = 121
Height = 25
Caption = 'Count all edits in panels'
TabOrder = 3
OnClick = btnAllEditsInPanelsClick
end
end
Комментарии:
1. Используйте класс коллекции
Ответ №1:
Вы выполняете итерацию только через элементы управления редактированием, которые являются прямыми дочерними элементами самой формы или последней созданной панели. Вы не перебираете все панели.
Используйте a TList
или другой подходящий контейнер для отслеживания изменений, которые вы создаете динамически, затем вы можете перебирать этот список / контейнер, когда это необходимо. И когда вы будете готовы удалить панель из формы, просто Remove()
удалите ее дочерний TEdit
элемент из списка, а затем Free()
панель, которая освободит TEdit
его для вас.
Например:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls,
System.Generics.Collections;
type
TfrmMain = class(TForm)
btnCreateNewObject: TButton;
btnCountValues: TButton;
btnCreateNewPanels: TButton;
btnAllEditsInPanels: TButton;
procedure btnCreateNewObjectClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure btnCountValuesClick(Sender: TObject);
procedure btnCreateNewPanelsClick(Sender: TObject);
procedure btnAllEditsInPanelsClick(Sender: TObject);
procedure DestroyPanel(Sender: TObject);
private
{ Private declarations }
AllEdits: TList<TEdit>;
yposition: integer;
ypositionpanel: integer;
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
procedure TfrmMain.btnCountValuesClick(Sender: TObject);
var
i, res: integer;
dynEdit: TEdit;
begin
res := 0;
for i := 0 to AllEdits.Count - 1 do
begin
dynEdit := AllEdits[i];
if dynEdit.Parent = Self then
res := res StrToInt(dynEdit.Text);
end;
ShowMessage(IntToStr(res));
end;
procedure TfrmMain.btnCreateNewObjectClick(Sender: TObject);
var
dynEdit: TEdit;
begin
dynEdit := TEdit.Create(Self);
try
with dynEdit do
begin
Parent := Self;
Width := 80;
Height := 25;
Top := yposition;
Left := 3;
end;
AllEdits.Add(dynEdit);
except
dynEdit.Free;
raise;
end;
yposition := yposition 26
end;
procedure TfrmMain.btnCreateNewPanelsClick(Sender: TObject);
var
dynPanel: TPanel;
dynEdit: TEdit;
dynButton: TButton;
begin
dynPanel := TPanel.Create(Self);
try
with dynPanel do
begin
Parent := Self;
Width := 200;
Height := 40;
Top := ypositionpanel;
Left := 120;
end;
dynEdit := TEdit.Create(dynPanel);
with dynEdit do
begin
Parent := dynPanel;
Width := 80;
Height := 25;
Top := 3;
Left := 3;
end;
dynButton := TButton.Create(dynPanel);
with dynButton do
begin
Parent := dynPanel;
Width := 100;
Height := 25;
Top := 3;
Left := 100;
Caption := 'Destroy this pnl';
onClick := DestroyPanel;
end;
AllEdits.Add(dynEdit);
except
dynPanel.Free;
raise;
end;
ypositionpanel := ypositionpanel 41;
end;
procedure TfrmMain.DestroyPanel(Sender: TObject);
var
dynPanel: TPanel;
dynEdit: TEdit;
begin
dynPanel := TPanel(TButton(Sender).Owner);
dynEdit := TEdit(dynPanel.Controls[0]);
AllEdits.Remove(dynEdit);
dynPanel.Free;
end;
procedure TfrmMain.btnAllEditsInPanelsClick(Sender: TObject);
var
i, res: integer;
dynEdit: TEdit;
begin
res := 0;
for i := 0 to AllEdits.Count - 1 do
begin
dynEdit := AllEdits[i];
if dynEdit.Parent <> Self then
res := res StrToInt(dynEdit.Text);
end;
ShowMessage(IntToStr(res));
end;
procedure TfrmMain.FormCreate(Sender: TObject);
begin
yposition := 1;
ypositionpanel := 1;
AllEdits := TList<TEdit>.Create;
end;
procedure TfrmMain.FormDestroy(Sender: TObject);
begin
AllEdits.Free;
end;
end.
Комментарии:
1. Хорошо, это работает, но как я могу получить выбранную панель, когда я могу удалить? У меня есть панель, редактирование и кнопка для удаления панели с ресурсами.
2. @pnieradko непонятно, чего вы хотите, поскольку вы не показали этого в своем вопросе. Но если кнопка является дочерним элементом панели, например, тогда просто используйте свойство кнопки
Parent
, чтобы найти панель.3. Если у меня есть, например, 5 панелей с кнопками редактирования и удаления, и я хочу удалить только одну с помощью кнопки, то как я могу удалить только одну панель? Могу ли я сделать тег в кнопке?
4. @pnieradko Опять же, вы не разъясняете, есть ли 5 кнопок, по одной на каждой панели, или 1 кнопка на самой форме. Если первое, то я уже ответил на это в своем последнем комментарии. Пожалуйста, отредактируйте свой вопрос, чтобы точно показать код, с которым у вас возникли проблемы.
5. @pnieradko вам не нужен список кнопок. И владельцем Кнопки должна быть Панель, а не Форма. Тем не менее, просто поместите код, который я уже дал вам ранее, непосредственно в обработчик события OnClick. Отправитель — это нажатая кнопка, просто введите отправителя в TButton, а затем введите его владельца в TPanel. Я обновил свой ответ, чтобы показать это.