Delphi의 부모 패널에 영향을 미치는 버튼 구성 요소
문제
삭제 및 추가 패널 버튼을 포함하여 각각 몇 가지 구성 요소가있는 동적으로 만든 패널로 구성된 프로그램을 작성하고 있습니다. 각 패널은 20 픽셀을 표시합니다. 패널 번호가 서로 아래로 표시되고, Add의 OnClick은 세트의 끝에 다른 패널을 추가해야하며 삭제를 위해 OnClick은 부모를 파괴 한 다음 다른 모든 패널을 삭제하는 공간으로 이동해야합니다. 내가 이미 시도한 방법은 배열을 사용하여 관련되었지만 불행히도 나는 그 중간에 객체를 삭제 한 배열을 통해 반복 할 때 eaccessviolation을 얻었습니다.
이것이 명백하거나 이전에 답변 된 경우 죄송합니다. 그러나 나는 이번 주 초에 나 자신을 가르치기 시작했기 때문에 모든 용어를 알지 못하거나 클래스가 나에게 이런 일을 할 배열이 있는지 모르겠습니다.
해결책
정렬 속성을 신중하게 사용 하여이 작업을 수행하는 것이 좋습니다.
여기에 표시된대로 정렬 된 3 개의 패널이있는 경우 :
|-----------------------|
| |
| alTop |
| |
|-----------------------|
|-----------------------|
| |
| alTop |
| |
|-----------------------|
|-----------------------|
| |
| alTop |
| |
|-----------------------|
그리고 두 번째를 삭제하면 세 번째는 자동으로 그 장소로 튀어 나옵니다.
3 개의 패널을 다른 부모 컨트롤 (즉, 다른 패널) 안에 배치하여 "altop"이라고 말할 때 "상단"이 무엇을 의미하는지 정의하십시오.
그 효과를 애니메이션하고 싶다면 약간 더 좋아해야합니다. 그게 당신의 목표인가요? 그렇다면, 우리가 무언가를 생각해 낼 수 있다고 확신합니다.
편집 - 나는 당신에게 몇 가지 아이디어를 줄 수있는 몇 가지 코드를 썼습니다.
unit Main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ExtCtrls;
type
TWhere = (wAtBeginning, wAtEnd);
type
TfrmMain = class(TForm)
panCtrl: TPanel;
panHost: TPanel;
btnAddPan: TBitBtn;
btnDelPan: TBitBtn;
lbAddWhere: TListBox;
lbDelWhere: TListBox;
procedure btnAddPanClick(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure btnDelPanClick(Sender: TObject);
private
function GetPanel(HostPanel: TPanel; Where: TWhere): TPanel;
function BottomOfLastPanel(HostPanel: TPanel): integer;
procedure AddPanel(HostPanel: TPanel; AddWhere: TWhere);
procedure DelPanel(HostPanel: TPanel; DelWhere: TWhere);
procedure DelThisPanel(Sender: TObject);
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
procedure TfrmMain.AddPanel(HostPanel: TPanel; AddWhere: TWhere);
var
pnl: TPanel;
btn: TBitBtn;
begin
pnl := TPanel.Create(HostPanel);
with pnl do begin
case AddWhere of
wAtBeginning: Top := 0;
wAtEnd: Top := BottomOfLastPanel(HostPanel);
end;
Align := alTop;
Parent := HostPanel;
Caption := DateTimeToStr(Now);
end;
btn := TBitBtn.Create(pnl);
with btn do begin
Parent := pnl;
Left := 0;
Top := 0;
Width := 100;
Height := 30;
Align := alLeft;
Caption := 'Delete this panel';
OnClick := DelThisPanel;
end;
end;
function TfrmMain.BottomOfLastPanel(HostPanel: TPanel): integer;
begin
//scan through all panels contained inside the host panel
//return the bottom of the lowest one (highest "top" value)
Result := 0;
if Assigned(GetPanel(HostPanel,wAtEnd)) then begin
Result := GetPanel(HostPanel,wAtEnd).Top + GetPanel(HostPanel,wAtEnd).Height;
end;
end;
procedure TfrmMain.btnAddPanClick(Sender: TObject);
begin
case lbAddWhere.ItemIndex of
0: AddPanel(panHost,wAtBeginning);
1: AddPanel(panHost,wAtEnd);
end;
end;
procedure TfrmMain.btnDelPanClick(Sender: TObject);
begin
case lbDelWhere.ItemIndex of
0: DelPanel(panHost,wAtBeginning);
1: DelPanel(panHost,wAtEnd);
end;
end;
procedure TfrmMain.DelPanel(HostPanel: TPanel; DelWhere: TWhere);
var
pnlToDelete: TPanel;
begin
case DelWhere of
wAtBeginning: pnlToDelete := GetPanel(HostPanel,wAtBeginning);
wAtEnd: pnlToDelete := GetPanel(HostPanel,wAtEnd);
end;
if Assigned(pnlToDelete) then begin
FreeAndNil(pnlToDelete);
end;
end;
procedure TfrmMain.DelThisPanel(Sender: TObject);
var
parentPnl: TPanel;
begin
//delete the parent panel of this button
if Sender is TBitBtn then begin
if (Sender as TBitBtn).Parent is TPanel then begin
parentPnl := (Sender as TBitBtn).Parent as TPanel;
parentPnl.Parent := nil;
FreeAndNil(parentPnl);
end;
end;
end;
procedure TfrmMain.FormShow(Sender: TObject);
begin
lbAddWhere.ItemIndex := 1;
lbDelWhere.ItemIndex := 1;
end;
function TfrmMain.GetPanel(HostPanel: TPanel; Where: TWhere): TPanel;
var
i: integer;
begin
Result := nil;
for i := 0 to panHost.ControlCount - 1 do begin
if panHost.Controls[i] is TPanel then begin
Result := (panHost.Controls[i] as TPanel);
if Where = wAtBeginning then begin
Break;
end;
end;
end;
end;
end.
그리고 다음은 DFM의 코드입니다.
object frmMain: TfrmMain
Left = 0
Top = 0
Caption = 'Add / Delete Panel Demo'
ClientHeight = 520
ClientWidth = 637
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 13
object panCtrl: TPanel
Left = 0
Top = 0
Width = 305
Height = 520
Align = alLeft
TabOrder = 0
object btnAddPan: TBitBtn
Left = 8
Top = 8
Width = 125
Height = 75
Caption = 'Add panel'
TabOrder = 0
OnClick = btnAddPanClick
end
object btnDelPan: TBitBtn
Left = 8
Top = 89
Width = 125
Height = 75
Caption = 'Remove panel'
TabOrder = 1
OnClick = btnDelPanClick
end
object lbAddWhere: TListBox
Left = 139
Top = 8
Width = 150
Height = 75
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Tahoma'
Font.Style = []
ItemHeight = 16
Items.Strings = (
'Add to the top'
'Add to the bottom')
ParentFont = False
TabOrder = 2
end
object lbDelWhere: TListBox
Left = 139
Top = 89
Width = 150
Height = 75
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Tahoma'
Font.Style = []
ItemHeight = 16
Items.Strings = (
'Delete from the top'
'Delete from the bottom')
ParentFont = False
TabOrder = 3
end
end
object panHost: TPanel
Left = 305
Top = 0
Width = 332
Height = 520
Align = alClient
TabOrder = 1
ExplicitLeft = 392
ExplicitTop = 264
ExplicitWidth = 185
ExplicitHeight = 41
end
end
다른 팁
동적 배열을 사용하고 패널을 제거 할 때 실제로 요소를 삭제하는 경우 배열 전략을 사용할 수 있습니다. 또는 요소가 할당 된 경우 (Array [i])와 함께 할당되는지 언제든지 확인할 수 있습니다.
그러나 배열 솔루션을 TcomponentList를 사용하여 솔루션으로 배열 솔루션을 교체하여 목록에 패널을 더 쉽게 추가하고 삭제할 수 있으며 이러한 유형의 상황에 맞게 설계되었습니다.