comment puis-je éviter ce comportement non désiré avec TSplitter de Delphi et les panneaux?

StackOverflow https://stackoverflow.com/questions/4835617

Question

Inclus est un petit projet qui démontre mon problème. J'ai un TPageControl aligné sur le formulaire principal. Sur chacun des deux tabsheets je panneaux client alignés. Sur chacun de ces panneaux, j'ai 2 et un séparateur sous-panneaux. Le panneau de gauche et le diviseur est aligné à gauche, le panneau RH client alignés.

Fondamentalement, le problème est l'interaction entre les 2 onglets. Pour démontrer:

  • exécuter le programme
  • étirer la principale forme horizontalement. Panel 3 augmentera
  • déplacer le séparateur jusqu'à à droite comme il ira. Panel 2 va croître, panneau 3 se rétracte à sa contrainte de min-largeur de 10 pixels.
  • sélectionnez tabsheet 2. Panel 5 est comme prévu, le panneau 6 a augmenté lorsque la principale forme a été étirée
  • réduire la largeur principale de forme à sa largeur d'origine. Panel 6 psy trop (indésirable)
  • cliquer sur tabsheet 1. forme principale de nouveau augmente en largeur (indésirable)

OK, le comportement est probablement explicable en termes des règles de panneaux alignés, mais quelqu'un peut-il suggérer des améliorations à l'opération?

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 
Était-ce utile?

La solution

To get expected behavior remove the constraints (MinWidth) from your panels. These settings are currently ineffective anyway, since your splitters have a MinSize of '30' (the default, not stored).

edit (response to the comment): You cannot expect the 'MinWidth' constraint of a control that's at the right side of a splitter to adjust the size of the left-side control. That's only logical, the constraint is a property for the control that you set. All you'll achieve is that the form will deny shrinking if your control is already at its 'MinWidth', hence the undesirable behavior that you observe that the form is getting larger when you switch tabs. What you desire, you have to do with code - as Marjan told in his answer. There should be more than one way to achieve this, for instance, put the below to the Panel3's 'OnCanResize' event:

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;

Autres conseils

Not necessarily a real answer, but a couple of remarks:

  • MinSize voor an alLeft aligned Splitter pertains to the control on the Splitter's left and right. Your Panel 6 is indeed resized to (slightly more than) its own minWidth (10) instead of the splitter's MinSize (30). You can more easily demonstrate this by adding two left aligned panels on each of your panels 2, 3, 5 and 6 and give them a width of 10 and 20 and a different color.

  • Selecting tabsheet one again after reducing the mainform's width, does grow the mainform (yikes) AND shows that now Panel3 has now also been reduced to its min width instead of the splitter's minSize.

The solution to the main form resizing? Dunno, but making sure your panels' minwidth is in sync with the splitters' minsize should remove the shrinking. And as Sertac says, I suspect that you simply need to opt for one or the other, but not both...

Update:

  • Setting the splitters' minSize to 30 and setting the panels' minWidth to 0. Takes away the mainform's resize, but does reduce the right hand panels to 0 width.

  • Setting the splitters' minSize to 30 and setting the panels' minWidth to 30, takes away the minimum width problems, but still resized the main form.

  • Setting the panels' minWidth to 30 and setting the splitters' minSize to 1 (the minimum) allows you to move the splitter all the way to the right and resizes the main form by the panels minWidth when you release the splitter. It does keep Panel6 from reducing to less than 30, but again the mainform resizes when you reselect tab 1.

It would seem that your best bet is to rely on the splitters' minSize and "manually" prevent the right hand panels from reducing to far by restricting the splitters' movement when it gets to far right. You can do this in the OnCanResize event of the splitters.

btw, using 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;
}

If while the form was wider you moved the splitter far to the right then reduced the form's width so it became narrower than the left-hand panel (and thus the splitter found itself 'outside' the form), what should the behaviour of your form be in this case? You have been asked about your criteria for desirable behaviour and all I can see in your answer so far is your understanding of undesirable behaviour.

Now I have been concerned a couple of times with possible side effects of resizing a form that has panels and splitters on it. I didn't investigate very much into it and so in particular I never knew before about the auto-resize effect like in your situations. Anyway, in order to prevent most (if not any) of the possible behavioral artefacts I considered using TScrollBox as a parent control to panels and splitters instead of TPanel.

I believe, this would change resizing of the form into resizing of the scroll box's client area, which would work fine for me in however few little projects of mine where I used splitters, if I employed tabsheets like you do. However I cannot know about your case. And I understand that this is more of a workaround than a solution to your problem.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top