Как мне избежать этого нежелательного поведения с помощью 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
,
Я полагаю, что это изменило бы изменение формы на изменение размера клиентской области окна прокрутки, что хорошо бы мне работало в тех немногих моих маленьких проектах, где я использовал сплиттеры, если бы использовал табуляцию, как вы. Однако я не могу знать о вашем случае. И я понимаю, что это скорее обходной путь, чем решение вашей проблемы.