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