Как мне избежать этого нежелательного поведения с помощью Delphi TSplitter и панелей?

В комплекте небольшой проект, демонстрирующий мою проблему. у меня есть TPageControl выровнен по основной форме. На каждой из двух вкладок у меня есть выровненные панели клиента. На каждой из этих панелей у меня есть 2 подпанели и сплиттер. Панель LH и сплиттер выровнены по левому краю, панель RH выровнена по клиенту.

В основном проблема заключается в взаимодействии между двумя вкладками. Показывать:

  • запустить программу
  • растянуть основную форму горизонтально. Панель 3 будет расти
  • переместите сплиттер как можно дальше вправо. Панель 2 будет расти, панель 3 будет уменьшена до минимального размера в 10 пикселей.
  • выберите вкладку 2. Панель 5 как и задумано, панель 6 выросла, когда основная форма была растянута
  • уменьшите ширину основной формы до ее первоначальной ширины. Панель 6 слишком сильно сжимается (нежелательно)
  • нажмите на таблицу 1. Основная форма снова увеличивается в ширине (нежелательно)

Хорошо, поведение, вероятно, объяснимо с точки зрения правил выровненных панелей, но кто-нибудь может предложить улучшения в работе?

unit Unit17;

interface

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

type
  TForm17 = class(TForm)
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    Panel1: TPanel;
    Panel2: TPanel;
    Splitter1: TSplitter;
    Panel3: TPanel;
    Panel4: TPanel;
    Splitter2: TSplitter;
    Panel5: TPanel;
    Panel6: TPanel;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form17: TForm17;

implementation

{$R *.dfm}

end.


object Form17: TForm17
  Left = 0
  Top = 0
  Caption = 'Form17'
  ClientHeight = 254
  ClientWidth = 314
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object PageControl1: TPageControl
    Left = 0
    Top = 0
    Width = 314
    Height = 254
    ActivePage = TabSheet1
    Align = alClient
    Constraints.MinWidth = 30
    TabOrder = 0
    ExplicitWidth = 480
    object TabSheet1: TTabSheet
      Caption = 'TabSheet1'
      ExplicitWidth = 281
      ExplicitHeight = 165
      object Panel1: TPanel
        Left = 0
        Top = 0
        Width = 306
        Height = 226
        Align = alClient
        Caption = 'Panel1'
        TabOrder = 0
        ExplicitWidth = 109
        ExplicitHeight = 165
        object Splitter1: TSplitter
          Left = 151
          Top = 1
          Width = 12
          Height = 224
          ExplicitLeft = 145
        end
        object Panel2: TPanel
          Left = 1
          Top = 1
          Width = 150
          Height = 224
          Align = alLeft
          Caption = 'Panel2'
          Constraints.MinWidth = 10
          TabOrder = 0
        end
        object Panel3: TPanel
          Left = 163
          Top = 1
          Width = 142
          Height = 224
          Align = alClient
          Caption = 'Panel3'
          Constraints.MinWidth = 10
          TabOrder = 1
          ExplicitLeft = 141
          ExplicitWidth = 330
        end
      end
    end
    object TabSheet2: TTabSheet
      Caption = 'TabSheet2'
      ImageIndex = 1
      ExplicitWidth = 281
      ExplicitHeight = 165
      object Panel4: TPanel
        Left = 0
        Top = 0
        Width = 306
        Height = 226
        Align = alClient
        Caption = 'Panel4'
        TabOrder = 0
        ExplicitWidth = 109
        ExplicitHeight = 165
        object Splitter2: TSplitter
          Left = 149
          Top = 1
          Width = 11
          Height = 224
          ExplicitLeft = 141
        end
        object Panel5: TPanel
          Left = 1
          Top = 1
          Width = 148
          Height = 224
          Align = alLeft
          Caption = 'Panel5'
          Constraints.MinWidth = 10
          TabOrder = 0
        end
        object Panel6: TPanel
          Left = 160
          Top = 1
          Width = 145
          Height = 224
          Align = alClient
          Caption = 'Panel6'
          Constraints.MinWidth = 10
          TabOrder = 1
          ExplicitLeft = 141
          ExplicitWidth = 139
          ExplicitHeight = 163
        end
      end
    end
  end
end 

4 ответа

Решение

Чтобы получить ожидаемое поведение, удалите ограничения (MinWidth) из ваших панелей. Эти настройки в настоящее время неэффективны, так как ваши сплиттеры имеют MinSize из 30 (по умолчанию, не сохраняется).

edit (ответ на комментарий): Вы не можете ожидать, что ограничение "MinWidth" для элемента управления, расположенного справа от разделителя, отрегулирует размер элемента управления с левой стороны. Это логично, ограничение является свойством для элемента управления, который вы устанавливаете. Все, чего вы добьетесь - это то, что форма будет отрицать сокращение, если ваш элемент управления уже имеет минимальную ширину, поэтому нежелательное поведение, которое вы наблюдаете, когда форма увеличивается при переключении вкладок. То, что вы хотите, вы должны делать с кодом - как сказал Марьян в своем ответе. Для этого должно быть несколько способов, например, поместить приведенное ниже в событие On3CanResize Panel3:

procedure TForm1.Panel3CanResize(Sender: TObject; var NewWidth,
  NewHeight: Integer; var Resize: Boolean);
begin
  if NewWidth < Splitter1.MinSize then
    Panel2.Width := Panel2.Width - Splitter1.MinSize + NewWidth;
end;

Не обязательно реальный ответ, но пара замечаний:

  • MinSize voor alleft выровненный Splitter относится к элементу управления слева и справа от Splitter. Размер вашей Panel 6 действительно (немного больше) собственного minWidth (10) вместо MinSize (30) разветвителя. Вы можете легко продемонстрировать это, добавив две выровненные по левому краю панели на каждую из ваших панелей 2, 3, 5 и 6 и назначив им ширину 10 и 20 и другой цвет.

  • Снова выбирая табулированную таблицу один после уменьшения ширины основной формы, она расширяет основную форму (yikes) И показывает, что теперь Panel3 теперь также уменьшена до ее минимальной ширины вместо minSize разделителя.

Решение основной формы изменения размера? Не знаю, но убедившись в том, что минимальная ширина ваших панелей синхронизирована с минимальным размером сплиттеров, следует устранить сжатие. И, как говорит Сертак, я подозреваю, что вам просто нужно выбрать один или другой, но не оба...

Обновить:

  • Установка minSize разделителей на 30 и установка minWidth панелей на 0. Убирает изменение размера основной формы, но уменьшает правые панели до 0 ширины.

  • Установка minSize разделителей на 30 и установка minWidth панелей на 30 устраняет проблемы минимальной ширины, но все же изменяет размер основной формы.

  • Установка minWidth панелей на 30 и установка minSize разделителей на 1 (минимум) позволяет перемещать разделитель полностью вправо и изменяет размер основной формы с помощью minWidth панелей, когда вы отпускаете разделитель. Это удерживает Panel6 от сокращения до менее 30, но опять же основная форма изменяет размеры при повторном выборе вкладки 1.

Казалось бы, вам лучше всего полагаться на minSize сплиттеров и "вручную" предотвращать уменьшение правых панелей, ограничивая движение сплиттеров, когда они доходят до правого края. Вы можете сделать это в событии OnCanResize разделителей.

кстати, используя D2009

void __fastcall TFMain::SplitterCanResize(TObject *Sender, int &NewSize, bool &Accept)
{
  TSplitter *S = (TSplitter *)Sender;
  for (int i = 0; Accept && i < S->Parent->ControlCount; i++) if (S->Parent->Controls[i]->Constraints->MaxHeight && S->Parent->Controls[i]->Align == S->Align && NewSize >= S->Parent->Controls[i]->Constraints->MaxHeight * 2) Accept = false;
}

Если в то время как форма была шире, вы переместили разделитель далеко вправо, а затем уменьшили ширину формы, чтобы она стала уже, чем левая панель (и, таким образом, разделитель оказался "вне" формы), каково поведение вашей формы? быть в этом случае? Вас спросили о ваших критериях желаемого поведения, и все, что я могу видеть в вашем ответе до сих пор, это ваше понимание нежелательного поведения.

Теперь я несколько раз беспокоился о возможных побочных эффектах изменения размера формы, в которой есть панели и разделители. Я не очень много в этом разбирался, и поэтому, в частности, я никогда раньше не знал об эффекте автоматического изменения размера, как в ваших ситуациях. В любом случае, для предотвращения большинства (если не каких-либо) возможных поведенческих артефактов, которые я рассматривал, используя TScrollBox в качестве родительского элемента управления для панелей и разделителей вместо TPanel,

Я полагаю, что это изменило бы изменение формы на изменение размера клиентской области окна прокрутки, что хорошо бы мне работало в тех немногих моих маленьких проектах, где я использовал сплиттеры, если бы использовал табуляцию, как вы. Однако я не могу знать о вашем случае. И я понимаю, что это скорее обходной путь, чем решение вашей проблемы.

Другие вопросы по тегам