¿Cómo evito este comportamiento no deseado con el TSplitter y los paneles de Delphi?
-
27-10-2019 - |
Pregunta
Se incluye un pequeño proyecto que demuestra mi problema.tengo un TPageControl
alineado con el formulario principal.En cada una de las dos hojas de pestañas tengo paneles alineados por el cliente.En cada uno de esos paneles tengo 2 subpaneles y un divisor.El panel izquierdo y el divisor están alineados a la izquierda, el panel derecho alineado con el cliente.
Básicamente el problema es la interacción entre las 2 pestañas.Demostrar:
- ejecuta el programa
- estire la forma principal horizontalmente.El panel 3 crecerá
- mueva el divisor lo más hacia la derecha posible.El Panel 2 crecerá, el Panel 3 se reducirá hasta su restricción de ancho mínimo de 10 píxeles.
- seleccione la pestaña 2.El panel 5 es tal como se diseñó, el panel 6 creció cuando se estiró la forma principal
- reduzca el ancho del formulario principal a su ancho original.El panel 6 se encoge demasiado (indeseable)
- haga clic en la pestaña 1.La forma principal vuelve a aumentar de ancho (indeseable)
Bien, el comportamiento probablemente se pueda explicar en términos de las reglas de los paneles alineados, pero ¿alguien puede sugerir mejoras en el funcionamiento?
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
Solución
Para obtener el comportamiento esperado, elimine las restricciones (MinWidth
) de sus paneles.Estas configuraciones están actualmente ineficaz de todos modos, dado que sus divisores tienen un MinSize
de '30' (el valor predeterminado, no almacenado).
editar (respuesta al comentario):No se puede esperar que la restricción 'MinWidth' de un control que está en el lado derecho de un divisor ajuste el tamaño del control del lado izquierdo.Eso es lógico, la restricción es una propiedad del control que usted establece.Todo lo que logrará es que el formulario negará la reducción si su control ya está en su 'MinWidth', de ahí el indeseable comportamiento que observa que el formulario se hace más grande cuando cambia de pestaña.Lo que deseas tiene que ver con el código, como dijo Marjan en su respuesta.Debería haber más de una manera de lograr esto, por ejemplo, coloque lo siguiente en el evento 'OnCanResize' del 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;
Otros consejos
No necesariamente una respuesta real, pero sí un par de comentarios:
MinSize para un Splitter alineado a la izquierda pertenece al control a la izquierda y a la derecha del Splitter.De hecho, su Panel 6 cambia de tamaño a (un poco más que) su propio minWidth (10) en lugar del MinSize (30) del divisor.Puede demostrar esto más fácilmente agregando dos paneles alineados a la izquierda en cada uno de sus paneles 2, 3, 5 y 6 y dándoles un ancho de 10 y 20 y un color diferente.
Al seleccionar la hoja de pestañas uno nuevamente después de reducir el ancho del formulario principal, el formulario principal crece (¡ay!) Y muestra que ahora Panel3 también se ha reducido a su ancho mínimo en lugar del tamaño mínimo del divisor.
¿La solución al cambio de tamaño del formulario principal?No sé, pero asegurarse de que el ancho mínimo de sus paneles esté sincronizado con el tamaño mínimo de los divisores debería eliminar la contracción.Y como dice Sertac, sospecho que simplemente hay que optar por uno u otro, pero no por ambos...
Actualizar:
Establecer el tamaño mínimo de los divisores en 30 y establecer el ancho mínimo de los paneles en 0.Elimina el cambio de tamaño del formulario principal, pero reduce los paneles de la derecha a 0 de ancho.
Establecer el tamaño mínimo de los divisores en 30 y el ancho mínimo de los paneles en 30 elimina los problemas de ancho mínimo, pero aún así cambia el tamaño del formulario principal.
Configurar el minWidth de los paneles en 30 y establecer el minSize de los divisores en 1 (el mínimo) le permite mover el divisor completamente hacia la derecha y cambiar el tamaño del formulario principal según el minWidth de los paneles cuando suelta el divisor.Evita que Panel6 se reduzca a menos de 30, pero nuevamente el formulario principal cambia de tamaño cuando vuelve a seleccionar la pestaña 1.
Parecería que su mejor opción es confiar en el tamaño mínimo de los divisores y evitar "manualmente" que los paneles del lado derecho se reduzcan demasiado restringiendo el movimiento de los divisores cuando llega al extremo derecho.Puedes hacer esto en el evento OnCanResize de los divisores.
Por cierto, usando 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;
}
Si mientras el formulario era más ancho movió el divisor mucho hacia la derecha y luego redujo el ancho del formulario para que se volviera más estrecho que el panel de la izquierda (y por lo tanto el divisor se encontró "fuera" del formulario), ¿cuál debería ser el comportamiento de su formulario? ser en este caso?Se le ha preguntado sobre sus criterios de comportamiento deseable y todo lo que puedo ver en su respuesta hasta ahora es su comprensión de Naciones Unidascomportamiento deseable.
Ahora me han preocupado un par de veces los posibles efectos secundarios de cambiar el tamaño de un formulario que tiene paneles y divisores.No investigué mucho al respecto y, en particular, nunca antes supe sobre el efecto de cambio de tamaño automático como en sus situaciones.De todos modos, para evitar la mayoría (si no alguno) de los posibles artefactos de comportamiento que consideré usar TScrollBox
como control principal para paneles y divisores en lugar de TPanel
.
Creo que esto cambiaría el tamaño del formulario para cambiar el tamaño del área de cliente del cuadro de desplazamiento, lo que funcionaría bien para mí en algunos de mis pequeños proyectos en los que usé divisores, si empleara hojas de pestañas como usted.Sin embargo no puedo conocer su caso.Y entiendo que esto es más una solución alternativa a su problema.