Как избежать этого нежелательного поведения с Tsplitter и панелями Delphi?
-
27-10-2019 - |
Вопрос
Включен небольшой проект, демонстрирующий мою проблему. у меня есть TPageControl
выровнен с основной формой. На каждом из двух таблиц у меня есть клиент панелей. На каждой из этих панелей у меня есть 2 подпанели и сплиттер. Панель LH и сплиттер выровнены слева, выровненная клиентская панель RH.
В основном проблема заключается в взаимодействии между 2 вкладками. Демонстрировать:
- Запустите программу
- Растяните основную форму горизонтально. Панель 3 будет расти
- Переместите сплиттер так далеко вправо, как это пойдет. Панель 2 будет расти, панель 3 будет сокращаться до своего 10-пиксельного ограничения шириной мин.
- Выберите TabSheet 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
Решение
Чтобы получить ожидаемое поведение, удалить ограничения (MinWidth
) из ваших панелей. Эти настройки в настоящее время неэффективный В любом случае, поскольку у ваших сплиттеров есть MinSize
из «30» (по умолчанию, не хранится).
редактировать (Ответ на комментарий): Вы не можете ожидать ограничения «MinWidth» управления, которое находится на правой стороне сплиттера, чтобы отрегулировать размер управления левой стороной. Это только логично, ограничение является свойством для установленного вами элемента управления. Все, чего вы достигнете, это то, что форма будет отрицать сокращение, если ваш контроль уже находится на его «Minweidth», отсюда нежелательно Поведение, которое вы наблюдаете, что форма становится все больше при переключении вкладок. То, что вы хотите, вы имеете отношение к коду - как сказал Марджан в своем ответе. Например, должно быть более одного способа достижения этого, чтобы поместить приведенное ниже событие «OnCanResize» панели 3:
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. Утвержденный выравниваемый сплиттер относится к управлению слева и справа. Ваша панель 6 действительно изменяется до (чуть больше, чем) его собственную меховину (10) вместо минсового размера сплиттера (30). Вы можете легче продемонстрировать это, добавив две левые выровненные панели на каждую из ваших панелей 2, 3, 5 и 6 и дать им ширину 10 и 20 и другой цвет.
Выбор табшита снова после уменьшения ширины Mainform, выращивает Mainform (yikes) и показывает, что теперь Panel3 также также была уменьшена до его ширины минима, а не до минимального размера сплиттера.
Решение основной формы изменения размера? Не знаю, но обеспечить синхронизацию ваших панелей, чтобы убедиться, что ваши панели синхронизируются с MinSize Splitters, должно удалить сокращение. И, как говорит Серт, я подозреваю, что вам просто нужно выбрать одного или другого, но не оба ...
Обновлять:
Установка расщепления до 30 и установка панелей «Минсиид» на 0. Убирает изменение размера Mainform, но снижает правую панели до 0 ширины.
Установка расщепления до 30 и установление панелей «Минсидэк» до 30, отнимает проблемы с минимальной шириной, но все же изменял размер основной формы.
Установка панелей «Minweedth» на 30 и установление MinSize расщепления до 1 (минимум) позволяет перемещать разветвитель вправо и изменяет размер основной формы на панелях MinWeidth, когда вы отпускаете сплиттер. Он не позволяет панели от сокращения до менее чем 30, но опять же, Mainform изменяется, когда вы выбираете вкладку 1.
Казалось бы, что лучше всего полагаться на MinSize Splitters и «вручную» предотвратить снижение правых панелей до далеко, ограничивая движение Splitters, когда оно попадает в правое. Вы можете сделать это в событии сплиттеров 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
.
Я полагаю, что это изменило бы изменение размера формы на изменение размера клиентской области Scroll Box, которая для меня будет хорошо работать в нескольких маленьких проектах, где я использовал сплиттеров, если бы я использовал таблицы, как вы. Однако я не могу знать о вашем деле. И я понимаю, что это скорее обходной путь, чем решение вашей проблемы.