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

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

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

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

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

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 of '30' (по умолчанию не сохраняется).

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

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 выровненный сплиттер относится к элементу управления слева и справа от сплиттера. Ваша панель 6 действительно имеет размер (немного больше) собственной minWidth (10) вместо MinSize (30) сплиттера. Вы можете легко продемонстрировать это, добавив две левые выровненные панели на каждой из ваших панелей 2, 3, 5 и 6 и дать им ширину 10 и 20 и другую цвет.

  • выбор tabsheet еще раз после уменьшения ширины mainform, увеличивает mainform (yikes) и показывает, что теперь Panel3 теперь также уменьшена до своей минимальной ширины вместо минимального размера сплиттера.

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

обновление:

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

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

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

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

btw, используя 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;
}

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

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

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