6 votes

comment éviter ce comportement indésirable avec le TSplitter et les panneaux de Delphi ?

Vous trouverez ci-joint un petit projet illustrant mon problème. J'ai un TPageControl alignés sur le formulaire principal. Sur chacune des deux feuilles de tabulation, j'ai des panneaux alignés sur le client. Sur chacun de ces panneaux, j'ai deux sous-panneaux et un séparateur. Le panneau gauche et le séparateur sont alignés à gauche, le panneau droit est aligné sur le client.

En fait, le problème est l'interaction entre les deux onglets. Pour démontrer :

  • exécuter le programme
  • étirer le formulaire principal horizontalement. Le panneau 3 s'agrandira
  • Déplacez le séparateur aussi loin que possible vers la droite. Le panneau 2 va s'agrandir, le panneau 3 va se rétrécir pour respecter la contrainte de largeur minimale de 10 pixels.
  • sélectionnez la feuille de calcul 2. Le panneau 5 est tel que conçu, le panneau 6 s'est agrandi lorsque le formulaire principal a été étiré.
  • réduire la largeur du formulaire principal à sa largeur initiale. Le panneau 6 rétrécit trop (indésirable)
  • cliquez sur la feuille d'onglets 1. La largeur du formulaire principal augmente à nouveau (indésirable).

OK, le comportement est probablement explicable en termes de règles de panneaux alignés, mais quelqu'un peut-il suggérer des améliorations de 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

4voto

Sertac Akyuz Points 32656

Pour obtenir le comportement attendu, supprimez les contraintes ( MinWidth ) de vos panneaux. Ces paramètres sont actuellement inefficace de toute façon, puisque vos séparateurs ont un MinSize de "30" (la valeur par défaut, non enregistrée).

modifier (réponse au commentaire) : Vous ne pouvez pas vous attendre à ce que la contrainte "MinWidth" d'un contrôle situé à droite d'un séparateur ajuste la taille du contrôle situé à gauche. C'est logique, la contrainte est une propriété du contrôle que vous définissez. Tout ce que vous obtiendrez, c'est que le formulaire refusera de se rétrécir si votre contrôle a déjà atteint sa "largeur minimale", d'où l'utilisation de l'expression "largeur minimale". indésirable que vous observez que le formulaire s'agrandit lorsque vous changez d'onglet. Ce que vous désirez, vous devez le faire avec du code - comme Marjan l'a dit dans sa réponse. Il devrait y avoir plus d'une façon d'y parvenir, par exemple, mettez le code suivant dans l'événement 'OnCanResize' du 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;

2voto

Marjan Venema Points 14626

Pas nécessairement une vraie réponse, mais quelques remarques :

  • MinSize voor an alLeft aligned Splitter concerne le contrôle à gauche et à droite du Splitter. Votre panneau 6 est effectivement redimensionné à (légèrement plus que) sa propre largeur minimale (10) au lieu de la taille minimale du séparateur (30). Vous pouvez plus facilement démontrer cela en ajoutant deux panneaux alignés à gauche sur chacun de vos panneaux 2, 3, 5 et 6 et en leur donnant une largeur de 10 et 20 et une couleur différente.

  • En sélectionnant à nouveau la tabsheet 1 après avoir réduit la largeur du formulaire principal, le formulaire principal s'agrandit (aïe) ET montre que maintenant Panel3 a également été réduit à sa largeur minimale au lieu de la taille minimale du splitter.

La solution au redimensionnement du formulaire principal ? Je ne sais pas, mais si vous vous assurez que la largeur minimale de vos panneaux est synchronisée avec la taille minimale des séparateurs, le rétrécissement devrait disparaître. Et comme le dit Sertac, je soupçonne que vous devez simplement opter pour l'un ou l'autre, mais pas pour les deux...

Mise à jour :

  • En fixant la taille minimale des séparateurs à 30 et la largeur minimale des panneaux à 0, on supprime le redimensionnement du formulaire principal, mais on réduit la largeur des panneaux de droite à 0.

  • En fixant la taille minimale des séparateurs à 30 et la largeur minimale des panneaux à 30, on élimine le problème de la largeur minimale, mais on redimensionne toujours le formulaire principal.

  • En fixant la largeur minimale des panneaux à 30 et la taille minimale des séparateurs à 1 (le minimum), vous pouvez déplacer le séparateur vers la droite et redimensionner le formulaire principal en fonction de la largeur minimale des panneaux lorsque vous relâchez le séparateur. Cela empêche Panel6 de se réduire à moins de 30, mais là encore, le formulaire principal est redimensionné lorsque vous resélectionnez l'onglet 1.

Il semblerait que votre meilleure option soit de vous fier à la taille minimale des séparateurs et d'empêcher "manuellement" les panneaux de droite de se réduire trop loin en limitant le mouvement des séparateurs lorsqu'ils arrivent à l'extrême droite. Vous pouvez le faire dans l'événement OnCanResize des séparateurs.

Au fait, j'utilise D2009

1voto

Цезарус Points 11
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;
}

0voto

Andriy M Points 40395

Si, alors que le formulaire était plus large, vous avez déplacé le séparateur loin vers la droite, puis réduit la largeur du formulaire pour qu'il devienne plus étroit que le panneau de gauche (et que le séparateur se retrouve donc "à l'extérieur" du formulaire), quel devrait être le comportement de votre formulaire dans ce cas ? On vous a demandé quels étaient vos critères de comportement souhaitable et tout ce que je peux voir dans votre réponse jusqu'à présent, c'est votre compréhension de ce qui suit un comportement souhaitable.

J'ai été préoccupé à plusieurs reprises par les effets secondaires possibles du redimensionnement d'un formulaire comportant des panneaux et des séparateurs. Je n'ai pas fait de recherches approfondies à ce sujet et, en particulier, je n'avais jamais entendu parler de l'effet de redimensionnement automatique comme dans votre cas. Quoi qu'il en soit, afin d'éviter la plupart (si ce n'est aucun) des artefacts comportementaux possibles, j'ai envisagé d'utiliser la fonction TScrollBox comme contrôle parent pour les panneaux et les séparateurs au lieu de TPanel .

Je pense que cela transformerait le redimensionnement du formulaire en un redimensionnement de la zone client de la boîte de défilement, ce qui me conviendrait parfaitement dans mes quelques petits projets où j'utilise des séparateurs, si j'employais des feuilles de tabulation comme vous le faites. Cependant, je ne peux pas connaître votre cas. Et je comprends que c'est plus une solution de contournement qu'une solution à votre problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X