2009-10-21 3 views
1

Я пишу программу, состоящую из динамически созданных панелей, каждая из которых имеет несколько компонентов, включая кнопки удаления и добавления панели. Каждая панель отображает 20 пикселей от номера панели ниже друг друга, OnClick для добавления должен добавить еще одну панель в конец набора, а OnClick для удаления должен уничтожить ее родительский элемент, а затем переместить все остальные панели в пространство, которое удаляет make. Метод, который я уже пытался использовать с использованием массива, но, к сожалению, я получил EAccessViolation при переходе через массив, где я удалил объект в середине.Компонент кнопки, влияющий на родительскую панель в Delphi

Извините, если это очевидно или ранее был дан ответ, но я только начал преподавать себя OO ранее на этой неделе, поэтому я не знаю всех терминов или если есть класс liek, массив, который будет делать это для меня.

ответ

4

Возможно, вам будет лучше сделать это, тщательно используя свойство Align.

Если у меня есть три панели с выравниванием, как показано здесь:

|-----------------------| 
|      | 
|  alTop   | 
|      | 
|-----------------------| 

|-----------------------| 
|      | 
|  alTop   | 
|      | 
|-----------------------| 

|-----------------------| 
|      | 
|  alTop   | 
|      | 
|-----------------------| 

И я уничтожаю вторую, то третий один будет автоматически выскочит в этом месте.

Просто разместите все три панели внутри другого родительского элемента управления (например, другую панель), чтобы определить, что означает «верх», когда мы говорим «alTop».

Если вы хотите оживить эффект, тогда вам нужно будет немного поучаствовать. Это ваша цель? Если это так, я уверен, что мы сможем что-то придумать.

Edit - Я написал код, который может дать вам некоторые идеи:

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 
+0

Thats выглядит как решение, с которым мне придется поэкспериментировать. Быстрый google для «Align Delphi» бросил меня обратно в эту тему: http://stackoverflow.com/questions/1259849/delphi-how-to-programmatically-adjust-visual-ordering-of-components-with-align Мне потребуется некоторое время, чтобы просмотреть их и понять их тоже. Спасибо. – BookOfGreg

+0

FYI, ваш пример также дает ошибку EAccessViolation при удалении объекта. Есть ли какая-то ошибка где-то? Я не могу определить один ... – BookOfGreg

+0

Хмм, я не получаю никаких нарушений доступа, когда добавляю или удаляю ... независимо от того, как я это делаю. Можете ли вы дать мне точные шаги, чтобы воспроизвести ошибку? Это каждый раз, когда вы удаляете панель или только последнюю, первую или что? Благодаря... – JosephStyons

0

Вы можете использовать стратегию массива если вы используете динамический массив и фактически удаляете элементы при удалении панелей. Кроме того, вы всегда можете проверить, назначен ли элемент, если Assigned (Array [I]).

Однако вам будет гораздо лучше заменить решение массива решением с помощью TComponentList, которое упростит добавление и удаление панелей в список и предназначено только для такого типа ситуаций.

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

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