Delphi:滑动(动画)面板

Posted

技术标签:

【中文标题】Delphi:滑动(动画)面板【英文标题】:Delphi: sliding (animated) panel 【发布时间】:2011-11-08 02:07:09 【问题描述】:

Delphi 是否有滑动(动画)面板组件?

例如,它可以在Raize Components(带有“热点”或隐藏/显示按钮的左侧面板)中找到。

我不需要一个可调整大小的面板,而是一个可以从左到右水平平滑滑动的面板 + 有一个隐藏/显示按钮(如果没有那个按钮,这没什么大不了的)。

谢谢!

【问题讨论】:

这篇文章可能有用:delphi.about.com/od/delphi-tips-2011/qt/… 在此处查看 FoldingPanel v1.3:torry.net/authorsmore.php?id=2386 我已经使用了多年。也有一个不错的人字形位图。 【参考方案1】:

试试NLDSideBar,这是我自己写的一个容器组件,可以折叠并沿其父级的左侧或右侧对齐。

界面:

property Align: TSideBarAlign default alLeft;
property AutoHide: Boolean default False;
property Hint: String;
property MinWidth: Integer default DefWidth;
property OnAutoHideChanged: TNotifyEvent;
property OnHide: TNotifyEvent;
property PinButtonDownHint: String;
property PinButtonUpHint: String;
property PinButtonVisible: Boolean default True;
property Resizable: Boolean default True;
property SideButtonWidth: Integer default DefSideButtonWidth;
property Caption;
property Color default clBtnFace;
property Font;
property ParentColor default False;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property TabOrder;
property TabStop;

或者可能是动画的this older version。免费使用,免费修改。

对不起,我自吹自擂,但我认为这是对问题的回答。

【讨论】:

你不必为自我推销道歉,只要你公开你的参与是完全可以接受的。 我将永远支持免费开源内容的自我推广! 如果他们完美地回答了这个问题,我将永远支持自我推销。 而且你似乎永远不会在 Delphi 7 之后更新它 :-) 我在 xe2 中尝试过,放了两个右侧面板 - 遗憾的是,我的行为不太直观......猜你总是只有一个侧面的面板:-) @Arioch'The 谢谢!这是一个错误。在UpdatePlacement中的每个块的末尾添加BringToFront【参考方案2】:

折叠面板 请在此处查看 FoldingPanel v1.3:http://www.torry.net/authorsmore.php?id=2386 我用了很多年。 它也带有漂亮的人字形位图。 小问题:它不支持复合控件(如 TLabeledEdit)。 优点:该组件以单个 PAS 文件的形式提供(易于安装到 Palette 中)。他们说它适用于 Delphi 5,但我将它安装在 XE7 中并且可以正常工作(这表明质量)。 免费软件

TSplitView 如果您有较新版本的 Delphi(如 Tokyo),您可以使用 TSplitView。 注意:它缺少 Align 属性。一开始它似乎只能与左对齐。但事实并非如此。它有一个 Placement 属性,而不是 Align 属性(具有两个值:svpRight / svpLeft)。 注意:它有一些与控件大小/位置相关的小故障。 注意:它不像 FoldingPanel 那样完整(甚至还没有)。您仍然需要编写一些代码来实现某种人字形来折叠/展开面板。https://www.youtube.com/watch?v=3hUG8o7PpCU 免费软件(如果您有 Delphi Tokyo)。

TCategoryPanelGroup 另请查看 TCategoryPanelGroup。它可能有效,也可能无效,具体取决于您的需要。 免费软件(如果你有 Delphi XE7)

【讨论】:

您与我们分享的好选择。【参考方案3】:

自 2009 版以来,有一个 TCategoryPanelGroup,您可以在其中添加 TCategoryPanel。

【讨论】:

谢谢! “我需要的不是可调整大小的面板,而是可以水平滑动的面板” 这个不可调整大小...但是,它只是垂直的;o(【参考方案4】:

我们最终构建了自己的控件。我们找不到任何符合我们要求的东西。结果没那么难。我确信有些情况我们没有正确处理,但是这对我们很有用。

下面的代码使用 cxGroupBox,因为我们需要它来匹配我们应用程序的其余部分。可以将其切换为普通的 GroupBox。

我们在两个地方使用它。在一种情况下,我们在标准的 Delphi Flow Panel 中有许多这样的面板(我不确定添加了哪个版本)。当我们的 DynPanel 折叠时,所有东西都会自动向上移动并填充空间。

在另一种情况下,我们有一个分为主要部分和工具箱的窗口。两者由标准分离器隔开。主窗口设置为与客户端对齐。当我们的面板折叠或展开时。拆分器会自动移动并展开主要部分。

我们从来没有完全让“容器”控件工作,因此您添加到面板的项目可以移动到您通常期望在组框中的范围之外。但这不会给我们带来任何重大问题,所以我们就离开了。这也没有考虑与按钮大小相关的 DPI 变化。标题会变大,但按钮不会。


unit DynPanel;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, cxGroupBox;

const
  DEFAULTBUTTONWIDTH = 16;
  DEFAULTWIDTH  = 161;
  DEFAULTHEIGHT = 81;
  cButtonPadding = 8;
  cCollapsePadding = 3;
  cCaptionPadding = '       ';
  cCollapsedSize = DEFAULTBUTTONWIDTH + cCollapsePadding;
  cAutoCollapseSize = DEFAULTBUTTONWIDTH + cButtonPadding;

type
  TCollapseDirection = (cdUp, cdRight, cdLeft);

  TMinDemension = cAutoCollapseSize..High(Integer);

  TDynPanel = class(TPanel)
  private
    FGroupBox: TcxGroupBox;
    FButtonPanel: TPanel;
    FButtonImage: TImage;

    FExpand: Boolean;
    FOldHeight: Integer;
    FOldWidth: Integer;
    FCollapseDirection: TCollapseDirection;
    FOrigGroupBoxCaption: String;
    FAutoCollapseHeight: TMinDemension;
    FAutoCollapseWidth: TMinDemension;

    FButtonPadding: integer;
    FCollapsePadding: integer;
    FCollapsedSize: integer;

    procedure SetExpand(Value: Boolean);
    procedure SetGroupBoxCaption(Value: string);
    procedure ButtonMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;
    procedure EnableControls(Value: Boolean);
    procedure SetCollapseDirection(Value: TCollapseDirection);
    procedure ConfigurePanel;
    procedure SetMinHeight(Value: TMinDemension);
    procedure SetMinWidth(Value: TMinDemension);
    procedure UpdateImage();

  protected
    procedure Resize; override;
    procedure ChangeScale(M, D: Integer); override;
  public
    constructor Create(AOwner: TComponent); override;
    property OldHeight: Integer read FOldHeight write FOldHeight;
    property OldWidth: Integer read FOldWidth write FOldWidth;
    property GroupBox: TcxGroupBox read FGroupBox;
  published
    property Caption: string read FOrigGroupBoxCaption write SetGroupBoxCaption;
    property Expand: Boolean read FExpand write SetExpand;
    property BevelOuter default bvNone;
    property CollapseDirection: TCollapseDirection read FCollapseDirection write SetCollapseDirection default cdUp;
    property AutoCollapseHeight: TMinDemension read FAutoCollapseHeight write SetMinHeight default cAutoCollapseSize;
    property AutoCollapseWidth: TMinDemension read FAutoCollapseWidth write SetMinWidth default cAutoCollapseSize;
  end;

procedure Register;

implementation

$R 'ButtonImages\ButtonImages.res' 'ButtonImages\ButtonImages.rc'

uses cxEdit;

procedure Register;
begin
  RegisterComponents('AgWare', [TDynPanel]);
end;


 TDynPanel 


  TDynPanel.Create
  ---------------------------------------------------------------------------

constructor TDynPanel.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  Self.ControlStyle := ControlStyle - [csSetCaption];

  Self.Width := DEFAULTWIDTH;
  Self.Height := DEFAULTHEIGHT;
  BevelOuter := bvNone;

  FExpand := True;
  FOldHeight := Self.Height;
  FOldWidth := Self.Width;
  FOrigGroupBoxCaption := 'AgDynPanel';
  FCollapseDirection := cdUp;
  FAutoCollapseHeight := cAutoCollapseSize;
  FAutoCollapseWidth := cAutoCollapseSize;

  FGroupBox := TcxGroupBox.Create(Self);
  FGroupBox.Parent := Self;
  FGroupBox.Align := alClient;
  FGroupBox.Alignment := alTopLeft;

  FButtonPanel := TPanel.Create(Self);
  FButtonPanel.Parent := Self;
  FButtonPanel.Top := 0;
  FButtonPanel.Width := DEFAULTBUTTONWIDTH;
  FButtonPanel.Height := DEFAULTBUTTONWIDTH;
  FButtonPanel.Left := Width - DEFAULTBUTTONWIDTH - FButtonPadding;
  FButtonPanel.OnMouseDown := ButtonMouseDown;

  FButtonImage := TImage.Create(Self);
  FButtonImage.Parent := FButtonPanel;
  FButtonImage.Align := alClient;
  FButtonImage.Stretch := false;
  FButtonImage.Center := true;
  FButtonImage.OnMouseDown := ButtonMouseDown;

  UpdateImage;

  // The click should also work for the entire top of the group box.
  FGroupBox.OnMouseDown := ButtonMouseDown;

  FGroupBox.Caption := FOrigGroupBoxCaption;
  FGroupBox.Style.Font.Style := FGroupBox.Style.Font.Style + [fsBold];

  FButtonPadding := cButtonPadding;
  FCollapsePadding := cCollapsePadding;
  FCollapsedSize := cCollapsedSize;

end;


  TDynPanel.SetGroupBoxCaption
  ---------------------------------------------------------------------------

procedure TDynPanel.SetGroupBoxCaption(Value: String);
begin
  FOrigGroupBoxCaption := Value;
  ConfigurePanel;
end;


  TDynPanel.SetMinHeight
  ---------------------------------------------------------------------------

procedure TDynPanel.SetMinHeight(Value: TMinDemension);
begin
  if Value = FAutoCollapseHeight then
    Exit; // >>----->

  FAutoCollapseHeight := Value;

  if Showing then
    Resize;
end;


  TDynPanel.SetMinWidth
  ---------------------------------------------------------------------------

procedure TDynPanel.SetMinWidth(Value: TMinDemension);
begin
  if Value = FAutoCollapseWidth then
    Exit; // >>----->

  FAutoCollapseWidth := Value;

  if Showing then
    Resize;
end;


  TDynPanel.ButtonMouseDown
  ---------------------------------------------------------------------------

procedure TDynPanel.ButtonMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if Button  mbLeft then
    Exit; // >>----->

  if ((FExpand = True) and (Y  FCollapsePadding)) or
     ((FExpand = False) and (FCollapseDirection = cdLeft) and (X >----->

  FExpand := Value;

  //ConfigurePanel;

  //--------------------------------------------------------------------------
  // Set the group box size
  //--------------------------------------------------------------------------
  //
  // I chose to do the resizing of the control here rather than in
  // ConfigurePanel because if you do it there the SetBounds will call ReSize
  // which will call ConfigurePanel again so that you would need to keep track
  // of a boolean variable to determine if you are making recursive calls into
  // ConfigurePanel. That is one reason. Another is that when the dfm values
  // are streamed in and the properties get set you will resize the control
  // before the actual Height and Width properties are set. This will cause
  // bogus default values to be stored for FOldHeight and FOldWidth and when
  // the control is displayed the dimensions will be wrong. If you size the
  // control here then, on creation, Resize will not get called and the
  // FOldHeight and FOldWidth values will not get saved off until
  // CMShowingChanged will explicitly call ReSize after the dimensions are
  // properly set. If you move this code into ConfigurePanel then when the
  // caption is streamed in and set from the dfm then ConfigurePanel would get
  // called, we would SetBounds there and then Resize would fire storing off the
  // default invalid values for the FOld variables as mentioned above.
  // Hope this makes sense. Leave the SetBounds calls here and make your life
  // easier. :)
  //--------------------------------------------------------------------------

  // Changing to Expanded
  if FExpand = True then
  begin
    // Up
    if FCollapseDirection = cdUp then
      SetBounds(Left, Top, Width, FOldHeight)
    // Right
    else if FCollapseDirection = cdRight then
      SetBounds((Left + Width) - FOldWidth, Top, FOldWidth, Height)
    // Left
    else if FCollapseDirection = cdLeft then
      SetBounds(Left, Top, FOldWidth, Height);
  end
  // Changing to Collapsed
  else
  begin
    // Up
    if FCollapseDirection = cdUp then
    begin
      // Reset the AutoCollapseHeight just to make sure we don't try to
      // recollapse on resize.
      if FAutoCollapseHeight  FGroupBox) and
       (Self.Controls[i]  FButtonPanel) then
    begin
      Self.Controls[i].Enabled := Value;
      Self.Controls[i].Visible := Value;
    end;
  end;
end;


  TDynPanel.CMShowingChanged
  ---------------------------------------------------------------------------

procedure TDynPanel.CMShowingChanged(var Message: TMessage);
begin
  inherited;
  if Showing then
    Resize;
end;


  TDynPanel.Resize
  ---------------------------------------------------------------------------

procedure TDynPanel.Resize;
begin

  if FExpand = True then
  begin
    if (FCollapseDirection = cdUp) and (Height  FAutoCollapseHeight then
      begin
        FOldHeight := Height;
        Expand := True;
      end
      else
        Height := FCollapsedSize;
    end
    else if (FCollapseDirection = cdLeft) or (FCollapseDirection = cdRight) then
    begin
      if (Width > FAutoCollapseWidth) then
      begin
        FOldWidth := Width;
        Expand := True;
      end
      else
        Width := FCollapsedSize;
    end;
  end;

  ConfigurePanel;

end;



  TDynPanel.ChangeScale
  ---------------------------------------------------------------------------

procedure TDynPanel.ChangeScale(M, D: Integer);
begin

  FAutoCollapseHeight := MulDiv(FAutoCollapseHeight, M, D);
  FAutoCollapseWidth := MulDiv(FAutoCollapseWidth, M, D);

  FButtonPadding := MulDiv(FButtonPadding, M, D);
  FCollapsePadding := MulDiv(FCollapsePadding, M, D);
  FCollapsedSize := MulDiv(FCollapsedSize, M, D);


  FOldHeight := MulDiv(FOldHeight, M, D);
  FOldWidth := MulDiv(FOldWidth, M, D);

  // inherited will cause resize to be called.  I need to update
  // my internal values before that happens, otherwise I will resize based
  // on the old values.
  inherited;

end;


  TDynPanel.SetCollapseDirection
  ---------------------------------------------------------------------------

procedure TDynPanel.SetCollapseDirection(Value: TCollapseDirection);
begin
  if Value = FCollapseDirection then
    Exit; // >>----->

  FCollapseDirection := Value;

  ConfigurePanel;
end;


  TDynPanel.ConfigurePanel
  ---------------------------------------------------------------------------

procedure TDynPanel.ConfigurePanel;
begin
  //--------------------------------------------------------------------------
  // Set the group box style, caption alignment, caption, button position, and
  // button image
  //--------------------------------------------------------------------------

  // Changing to Expanded
  if FExpand = True then
  begin
    FGroupBox.Style.Color := clWhite;
    // Up
    if FCollapseDirection = cdUp then
    begin
      FGroupBox.Alignment := alTopLeft;
      FGroupBox.Caption := FOrigGroupBoxCaption;
      FButtonPanel.Top := 0;
      FButtonPanel.Left := Width - FButtonPanel.Width - FButtonPadding;
    end
    // Right
    else if FCollapseDirection = cdRight then
    begin
      FGroupBox.Alignment := alTopLeft;
      FGroupBox.Caption := '       ' + FOrigGroupBoxCaption;
      FButtonPanel.Top := 0;
      FButtonPanel.Left := FButtonPadding;
    end
    // Left
    else if FCollapseDirection = cdLeft then
    begin
      FGroupBox.Alignment := alTopLeft;
      FGroupBox.Caption := FOrigGroupBoxCaption;
      FButtonPanel.Top := 0;
      FButtonPanel.Left := Width - FButtonPanel.Width - FButtonPadding;
    end;
  end
  // Changing to Collapsed
  else
  begin
    FGroupBox.Style.Color := clGradientActiveCaption;
    // Up
    if FCollapseDirection = cdUp then
    begin
      FGroupBox.Alignment := alTopLeft;
      FGroupBox.Caption := FOrigGroupBoxCaption;
      FButtonPanel.Top := 0;
      FButtonPanel.Left := Width - FButtonPanel.Width - FButtonPadding;
    end
    // Right
    else if FCollapseDirection = cdRight then
    begin
      FGroupBox.Alignment := alRightTop;
      FGroupBox.Caption := '       ' + FOrigGroupBoxCaption;
      FButtonPanel.Top := FButtonPadding;
      FButtonPanel.Left := FCollapsePadding;
    end
    // Left
    else if FCollapseDirection = cdLeft then
    begin
      FGroupBox.Alignment := alLeftTop;
      FGroupBox.Caption := FOrigGroupBoxCaption + '       ';
      FButtonPanel.Top := FButtonPadding;
      FButtonPanel.Left := 0;
    end;
  end;

  UpdateImage;
  // Now draw the button and invalidate Self
  Self.Invalidate;
end;


  TDynPanel.UpdateImage
  ---------------------------------------------------------------------------

procedure TDynPanel.UpdateImage();
begin
  case FCollapseDirection of
    cdUp:
      begin
        if FExpand = true then
          FButtonImage.Picture.Bitmap.LoadFromResourceName(HInstance, 'ButtonImageUp')
        else
          FButtonImage.Picture.Bitmap.LoadFromResourceName(HInstance, 'ButtonImageDown');
      end;
    cdLeft:
      begin
        if FExpand = true then
          FButtonImage.Picture.Bitmap.LoadFromResourceName(HInstance, 'ButtonImageLeft')
        else
          FButtonImage.Picture.Bitmap.LoadFromResourceName(HInstance, 'ButtonImageRight');
      end;
    cdRight:
      begin
        if FExpand = true then
          FButtonImage.Picture.Bitmap.LoadFromResourceName(HInstance, 'ButtonImageRight')
        else
          FButtonImage.Picture.Bitmap.LoadFromResourceName(HInstance, 'ButtonImageLeft');
      end;
  end;

end;

end.

靠左

接近顶部


【讨论】:

看起来不错。但是您没有指定许可证 :-) 它是否考虑了两个或三个侧边栏并排的选项? @Arioch'我认为代码包含在默认的 *** CC 许可下。如果您需要与我不同的东西,您可以在“unlicense”unlicense.org 下使用它。我没有并排尝试过多个项目。我们将它与流面板垂直使用。我们的主编辑屏幕作为其中的 10 多个堆叠在流面板上,然后位于滚动框内。 CC 也有很多“版本”。 “我认为代码包含在默认的 *** CC 许可下” - 好吧,您可能会这么认为,但任何尝试使用它的人都会面临“比抱歉更安全”的问题。我可以接受任何非病毒 FLOSS 许可证,但由于时间不够,我可能会坚持使用 TCategoryPnel,尽管它不能满足我的所有愿望......【参考方案5】:

新的 Delphi 版本将包括这种滑动面板(通过 FireMonkey 的集成,以前称为 vgScene/dxScene)。您只需要点击高度或位置道具,一个选项将允许为此创建动画,并带有各种选项(插值类型、持续时间等)。

【讨论】:

如果 OP 使用 Firemonkey,这将是一个很好的答案。你不能很容易地在 VCL 应用程序中使用 FMX 控件:-) 我同意京东。在这里提及 Firemonkey 并没有帮助。

以上是关于Delphi:滑动(动画)面板的主要内容,如果未能解决你的问题,请参考以下文章

wxWidgets 中的动画滑动面板/窗口

jQuery - 显示滑动面板时动画绝对定位的 div 的“左”位置

Swiftui 动态动画面板从下到上

matlabgui滑动条看不见

axure动态面板滑动与拖动的区别?

可堆叠面板 Delphi 组件