IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

AWT/Swing Java Discussion :

Ajout dynamique de composant dans un panel et resize automatique du panel


Sujet :

AWT/Swing Java

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2014
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2014
    Messages : 51
    Points : 20
    Points
    20
    Par défaut Ajout dynamique de composant dans un panel et resize automatique du panel
    Bonjour,

    j'ai dans un JPanel un JSpinner qui contient des valeurs entières positives définissante un nombre de données, et pour chaque donnée l'utilisateur doit définir une valeur minimum et une maximum.

    J'ai dans le JPanel une sous classe de JPanel, DataRangePanel, qui contient deux JSpinner pour définir les intervalles de donnée.

    Le JPanel parent contient un ArrayList de DataRangePanel et implémente ChangeListener. Quand l'état du JSpinner est modifié, des DataRangePanel sont ajouté ou supprimé de l'ArrayList et du PanelParent, le panel parent est resizé et repaint afin que les changement soient bien pris en compte.

    Mais ça ne marche pas ! Je crois que c'est un problème de layout, j'ai beau cherché je ne sais pas quoi essayer...

    Voici le code du JPanel :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
        /**
         * Panel for data types entries, including number of datas and ranges for each datas
         */
        public class DataTypesPanel extends JPanel implements ChangeListener {
     
            //*****************************
            //  ATTRIBUTES
            //*****************************
     
            private JSpinner numberOfDatasSpin;
     
            private DataRangesPanel dataRangesPanel;
     
     
     
            //*****************************
            //  CONSTRUCTOR
            //*****************************
            public DataTypesPanel(int _numberOfDatas) {
                super();
     
                this.setLayout(new GridBagLayout());
     
                TitledBorder thisBorder = new TitledBorder("Données");
                this.setBorder(thisBorder);
     
                numberOfDatasSpin  = new JSpinner(new SpinnerNumberModel(_numberOfDatas, 1, Integer.MAX_VALUE, 1));
                numberOfDatasSpin.addChangeListener(this);
                TitledBorder numberBorder   = new TitledBorder("Nombre de données");
                numberOfDatasSpin.setBorder(numberBorder);
                GridBagConstraints gbcNODS  = new GridBagConstraints();
                gbcNODS.gridx = 0;
                gbcNODS.gridy = 0;
                gbcNODS.gridwidth   = 1;
                gbcNODS.gridheight  = 1;
                this.add(numberOfDatasSpin, gbcNODS);
     
                dataRangesPanel = new DataRangesPanel(_numberOfDatas);
                GridBagConstraints gbcDRP  = new GridBagConstraints();
                gbcDRP.gridx = 1;
                gbcDRP.gridy = 0;
                gbcDRP.gridwidth   = 1;
                gbcDRP.gridheight  = 1;
                this.add(dataRangesPanel, gbcDRP);
     
            }
     
     
     
            /**
             * Change the number of DataRangePanel when JSpinner numberOfDatasSpin's
             * state changed
             * @param e 
             */
            @Override
            public void stateChanged(ChangeEvent e){
                int number  = (int)((JSpinner)e.getSource()).getValue();
     
                if (number < dataRangesPanel.numberOfPanels()) {
                    for (int i = number; i < dataRangesPanel.numberOfPanels(); ) { // no incrementaion !!! Size automatically decrease, incredible !!!
                        dataRangesPanel.removeDataRange();
                    }
                }
                else if (number > dataRangesPanel.numberOfPanels()) {
                    for (int i = dataRangesPanel.numberOfPanels(); i < number; i++) {
                        dataRangesPanel.addDataRange();
                    }
                }
                dataRangesPanel.setPreferredSize(dataRangesPanel.getPreferredSize());
                this.setPreferredSize(this.getPreferredSize());
                repaint();
            }
     
     
     
            //*****************************
            //  INTERNAL CLASSES
            //*****************************
            public class DataRangesPanel extends JPanel {
     
                //****************************
                // ATTRIBUTES
                //****************************
                private ArrayList<DataRangePanel> dataRanges = new ArrayList<>();
     
                JScrollPane jsp;
     
                //****************************
                // CONSTRUCTOR
                //****************************
     
                public DataRangesPanel(int _numberOfDatas) {
                    super();
                    TitledBorder thisBorder = new TitledBorder("Echelles de valeur");
                    this.setBorder(thisBorder);
                    this.setLayout(new GridLayout(0, 1));
     
     
                    jsp = new JScrollPane(this);
                    jsp.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
                    jsp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
     
     
     
                    // Creation and addition of all DataRangePanel
                    for (int i = 0; i < _numberOfDatas; i++)
                        addDataRange();
     
     
     
                }
     
                //****************************
                // METHODS
                //****************************
     
                /**
                 * Create a new data internal DataRangePanel and add it to this panel
                 */
                public void addDataRange() {
                    int index   = dataRanges.size();
                    System.out.println("Add dataRange : " + index);
                    dataRanges.add(new DataRangePanel(index));
                    this.add(dataRanges.get(index));
                    this.setPreferredSize(this.getPreferredSize());
                    repaint();
                }
     
     
     
                /**
                 * Remove last DataRangePanel of this panel
                 */
                public void removeDataRange() {
                    int index   = dataRanges.size() - 1;
                    this.remove(dataRanges.get(index));
                    dataRanges.remove(index);
                    this.setPreferredSize(this.getPreferredSize());
                    repaint();
                }
     
     
     
     
                /**
                 * 
                 * @return the array of DataType obtained from the entries
                 */
                public DataType[] getDataTypes() {
                    DataType[] dataTypes = new DataType[dataRanges.size()];
     
                    for (int i = 0; i < dataTypes.length; i++)
                        dataTypes[i] = new DataType(dataRanges.get(i).getMinVal(), dataRanges.get(i).getMaxVal(), i);
     
                    return dataTypes;
                }
     
     
     
     
                /**
                 * 
                 * @return the number of DataRangePanel in this panel
                 */
                public int numberOfPanels() {
                    return dataRanges.size();
                }
     
                //****************************
                //  INTERNAL CLASS
                //****************************
                public class DataRangePanel extends JPanel {
                            //*****************************
                            //  ATTRIBUTES
                            //*****************************
                            private final int   index;
                            private JSpinner    val1Spin  = new JSpinner(new SpinnerNumberModel(-15, Integer.MIN_VALUE/2, Integer.MAX_VALUE, 5));
                            private JSpinner    val2Spin  = new JSpinner(new SpinnerNumberModel(30, Integer.MIN_VALUE/2, Integer.MAX_VALUE/2, 5));
     
     
                            //*****************************
                            //  CONSTRUCTOR
                            //*****************************
                            public DataRangePanel(int _index) {
     
                                index = _index;
                                this.setLayout(new GridLayout(0, 2));
                                TitledBorder    val1Border  = new TitledBorder("min/max");
                                val1Spin.setBorder(val1Border);
                                this.add(val1Spin);
     
                                TitledBorder    val2Border  = new TitledBorder("min/max");
                                val2Spin.setBorder(val2Border);
                                this.add(val2Spin);
     
                                TitledBorder    dataRangeBorder  = new TitledBorder("donnée " + _index);
                                this.setBorder(dataRangeBorder);
                                //JLabel  label = new JLabel("donnée " + _index);
                                //label.setLabelFor(this);
                                val1Spin.setPreferredSize(new Dimension(500,500));
                                val1Spin.setPreferredSize(new Dimension(500,500));
     
                            }
    Les méthodes censées modifier l'affichage sont addDataRange() et removeDataRange().

    Merci !

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    Dans addDataRange() et removeDataRange(), juste avant repaint(), ajoute revalidate() pour provoquer le relayouting.

    Tu dois pouvoir enlever dans stateChanged (qui de toute façon ne servent à rien, car il faudrait plutôt faire un revalidate() à la place) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    dataRangesPanel.setPreferredSize(dataRangesPanel.getPreferredSize());
    this.setPreferredSize(this.getPreferredSize());
    Le revalidate() invalide puis valide la hiérarchie de composant en remontant la hiérarchie, donc les addDataRange et removeDateRange appelés dans la méthode devrait suffire à provoquer le relayouting.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2014
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2014
    Messages : 51
    Points : 20
    Points
    20
    Par défaut
    Yes ça marche !

    Je ne connaissais pas revalidate(), elle s'occupe donc du layout...

    En tout cas c'est super ça marche nickel.
    Maintenant j'ai un autre petit soucis concernant le comportement, j'aimerais bien pouvoir ajouter un scroller sur le panel quand il y à trop de panel à l'intérieur.
    J'ai créé un JScrollPane avec mon JPanel parent en argument, avec les attributs de scroll si besoin et une taille préférée fixée.
    Mais lors de l'affichage tout est ratatiné !

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Quand tu dis "ratatiné", j'imagine quelque chose (une copie d'écran aurait été plus paralant par exemple) : lorsqu'on met des composants dans un GridLayout, ou dans un GridBagLayout avec expansion (avec weighty!=0), les composants vont être répartis dans l'espace disponible, en intercallant des espaces. Tant que ces espaces ne sont pas "nuls", ils pourrent être réduits afin de mettre un composant de plus. Dès qu'il n'y a plus d'espace disponible, la taille du conteneur augmente et les barres de scroll apparaissent.

    Normalement, un JPanel s'adapte automatiquement dans un JScrollPane, par rapport au preferredSize. Mais il y a quelque chose qui ne pas dans ton code : le JScrollPane est interne à la classe DataRangesPanel : il n'est donc pas possible qu'il soit ajouté dans la hiérarchie. Donc je pense, qu'en plus de l'effet dont je parlais avant, tu n'as même pas de scrollpane, tant qu'on ajoute des composants, le layout essaye de les répartir dans l'espace disponible, qui lui ne change pas, donc ils se ratatinent comme tu dis.
    A noter, que quand tu ajoutes le DataRangesPanel au JScrollPane, il s'y trouve bien, mais temporairement, car ensuite tu vas ajouter le DataRangesPanel à son conteneur final : un composant ne pouvant être dans un conteneur à la fois, il va être retiré du JScrollPane. Il n'y sera donc jamais.

    Normalement, on doit avoir :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    JPanel conteneur1 = ... // le conteneur parent, par exemple le contentPane de la fenêtre
     
    JPanel conteneur2 = ... // le conteneur qu'on veut scrollable
     
    conteneur1.add ( new JScrollPane( conteneur2 ) ); // il suffit de faire ça
    Un exemple de principe plus parlant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    public class JScrollPaneDemo {
     
    	public static void main(String[] args) {
     
    		SwingUtilities.invokeLater(()-> new JScrollPaneDemo().run());
     
    	}
     
    	private final AtomicInteger ID = new AtomicInteger();
     
    	public void run() {
    		JFrame frame = new JFrame("Démo");
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		frame.getContentPane().add(createPanel());
     
    		frame.pack();
    		frame.setSize(300,frame.getHeight());
     
    		frame.setLocationRelativeTo(null);
    		frame.setVisible(true);
    	}
     
    	private Component createPanel() {
    		JPanel parent = new JPanel(new BorderLayout());
     
    		JPanel conteneur = new JPanel(new GridBagLayout());
    		for(int i=0; i<10; i++) {
    			createChild(conteneur);
    		}
    		parent.add(new JScrollPane(conteneur, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER),BorderLayout.CENTER);
     
    		JButton button = new JButton("Ajouter");
    		button.addActionListener(e-> addChild(conteneur));
    		parent.add(button, BorderLayout.SOUTH);
     
    		return parent;
    	}
     
    	private void addChild(JPanel conteneur) {
    		JComponent child = createChild(conteneur);
    		child.revalidate();
    		SwingUtilities.invokeLater(()->child.scrollRectToVisible(child.getBounds()));
    	}
     
    	private JComponent createChild(JPanel conteneur) {
    		int y=ID.getAndIncrement();
    		JLabel label = new JLabel("Bidule "+(y+1));
    		conteneur.add(label, new GridBagConstraints(0, y, 1, 1, 1, /*un 1 ici aurait l'effet de "ratatinage"*/0, GridBagConstraints.BASELINE_LEADING, GridBagConstraints.HORIZONTAL, new Insets(2,1,2,1), 0, 0));
    		return label;
    	}
     
    }

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2014
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2014
    Messages : 51
    Points : 20
    Points
    20
    Par défaut
    Oui effectivement je ne peux pas ajouter le composant dans plusieurs conteneurs, j'avais omis cette ligne...

    Dans un JPanel j'ai mon JSpinner et mon DataRangesPanel que j'aimerais pouvoir scroller.
    Dans ce même JPanel on trouve maintenant le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    // on est encore sur un GridBagLayout
     
    this.add(numberOfDatasSpin, gbcNODS);  // le spinner
     
    jsp = new JScrollPane(dataRangesPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    jsp.setPreferredSize(new Dimension(500, 500));
    this.add(jsp, gbcDRP);
    Et dans le DataRangesPanel avant j'était sur un GridLayout et je suis passé sur un GridBagLayout en copiant collant les contraintes que tu utilise dans ton exemple. Je pensait qu'avec un simple GridLayout ça irait.
    Voici donc ce que j'obtiens :

    Nom : scrollbar_problem.jpg
Affichages : 1227
Taille : 5,8 Ko

  6. #6
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Ce n'est pas tant le problème du GridLayout que du JScrollPanel. Avec le GridLayout, les composants sont répartis dans l'espace qu'on leur donne : pas assez de place = ratatinage, trop de place = plein d'espace entre les composants. Avec le GridBagLayout on a meilleur contrôle : mais tout dépend des paramètres des contraintes. Là, déjà j'ai l'impression que tu as 2 composants donc tu ne peux pas directement utiliser la contrainter que j'ai utilisé qui ne fonctionne que pour la colonne 0 (le deuxième paramètre).

    Donc ça marche aussi avec un GridLayout (mais si tu étends la fenêtre, les items s'écartent) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    public class JScrollPaneDemo {
     
    	public static void main(String[] args) {
     
    		SwingUtilities.invokeLater(()-> new JScrollPaneDemo().run());
     
    	}
     
    	private final AtomicInteger ID = new AtomicInteger();
     
    	public void run() {
    		JFrame frame = new JFrame("Démo");
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		frame.getContentPane().add(createPanel());
     
    		frame.pack();
    		frame.setSize(300,frame.getHeight());
     
    		frame.setLocationRelativeTo(null);
    		frame.setVisible(true);
    	}
     
    	private Component createPanel() {
    		JPanel parent = new JPanel(new BorderLayout());
     
    		JPanel conteneur = new JPanel(new GridLayout(0,1));
    		for(int i=0; i<10; i++) {
    			createChild(conteneur);
    		}
    		parent.add(new JScrollPane(conteneur, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER),BorderLayout.CENTER);
     
    		JButton button = new JButton("Ajouter");
    		button.addActionListener(e-> addChild(conteneur));
    		parent.add(button, BorderLayout.SOUTH);
     
    		return parent;
    	}
     
    	private void addChild(JPanel conteneur) {
    		JComponent child = createChild(conteneur);
    		child.revalidate();
    		SwingUtilities.invokeLater(()->child.scrollRectToVisible(child.getBounds()));
    	}
     
    	private JComponent createChild(JPanel conteneur) {
    		int y=ID.getAndIncrement();
    		JLabel label = new JLabel("Bidule "+(y+1));
    		conteneur.add(label);
    		return label;
    	}
     
    }


    Le problème principal c'était juste d'arborescence conteneur / scrollpane / container : avec ton code tu avais conteneur / container.

    Par ailleurs, si je comprends bien, c'est chaque composant que tu voudrais avoir scrollable, le tout dans un scrollable. Dans ce cas, il faut que chaque composant ait une taille, sinon ils ont s'étendre ou se compresser selon la place qu'on leur laisse.

    Avec gridlayout, d'ailleurs si la fenêtre est trop grande, on aura étirage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    public class JScrollPaneDemo extends AbstractComponent<Component> {
     
    	public static void main(String[] args) {
     
    		SwingUtilities.invokeLater(()-> run());
     
    	}
     
    	public static void run() {
    		JFrame frame = new JFrame("Démo");
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		frame.getContentPane().add(new JScrollPaneDemo(10,0));
     
    		frame.setSize(300,400);
     
    		frame.setLocationRelativeTo(null);
    		frame.setVisible(true);
    	}
     
    	public JScrollPaneDemo(int initComp, int visibleComp) {
    		super(initComp, visibleComp);
    		createPanel();
    	}
     
    	protected Component createChild(JPanel parent) {
    		Component component = new Component(7,3);
    		parent.add(component);
    		return component;
    	}
     
    }
    abstract class AbstractComponent<C extends JComponent> extends JPanel {
     
    	protected final int initComp;
    	protected final int visibleComp;
     
    	public AbstractComponent(int initComp, int visibleComp) {
    		super(new BorderLayout());
    		this.initComp=Math.max(0,initComp);
    		this.visibleComp=Math.min(initComp, visibleComp);
    	}
     
    	protected Dimension createPanel() {
    		JPanel conteneur = new JPanel(new GridLayout(0,1));
    		for(int i=0; i<initComp; i++) {
    			createChild(conteneur);
    		}
    		add(new JScrollPane(conteneur, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER),BorderLayout.CENTER);
     
    		JButton button = new JButton("Ajouter");
    		button.addActionListener(e-> addChild(conteneur));
    		add(button, BorderLayout.SOUTH);
    		Dimension dimension = button.getPreferredSize();
    		dimension.height+=getConteneurHeight(conteneur.getPreferredSize().getHeight(),getInsets());
    		return dimension;
    	}
     
    	private double getConteneurHeight(double height, Insets insets) {
    		int margin=insets.top+insets.bottom;
    		height-=margin;
    		height=(height/initComp)*visibleComp;
    		return height+margin;
    	}
     
    	private JComponent addChild(JPanel parent) {
    		JComponent child = createChild(parent);
    		child.revalidate();
    		SwingUtilities.invokeLater(()->child.scrollRectToVisible(child.getBounds()));
    		return child;
    	}
     
    	protected abstract C createChild(JPanel parent);
     
    }
    class Component extends AbstractComponent<JLabel> {
     
    	private final AtomicInteger ID = new AtomicInteger();
     
    	public Component(int initComp, int visibleComp) {
    		super(initComp, visibleComp);
    		Dimension dimension = createPanel();
    		setPreferredSize(dimension);
    		setMaximumSize(dimension);
    	}
     
    	protected JLabel createChild(JPanel parent) {
    		int y=ID.getAndIncrement();
    		JLabel label = new JLabel("Bidule "+(y+1));
    		parent.add(label);
    		return label;
    	}
     
    }


    Avec GridBagLayout et les contraintes que j'utilise, on a répartition de l'espace supplémentaire au-dessus et en-dessous :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    public class JScrollPaneDemo extends AbstractComponent<Component> {
     
    	public static void main(String[] args) {
     
    		SwingUtilities.invokeLater(()-> run());
     
    	}
     
    	public static void run() {
    		JFrame frame = new JFrame("Démo");
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		frame.getContentPane().add(new JScrollPaneDemo(10,0));
     
    		frame.setSize(300,400);
     
    		frame.setLocationRelativeTo(null);
    		frame.setVisible(true);
    	}
     
    	public JScrollPaneDemo(int initComp, int visibleComp) {
    		super(initComp, visibleComp);
    		createPanel();
    	}
     
    	protected Component createChild(JPanel parent) {
    		Component component = new Component(7,3);
    		parent.add(component, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1, /*un 1 ici aurait l'effet de "ratatinage"*/0, GridBagConstraints.BASELINE_LEADING, GridBagConstraints.HORIZONTAL, new Insets(2,1,2,1), 0, 0));
    		return component;
    	}
     
    }
    abstract class AbstractComponent<C extends JComponent> extends JPanel {
     
    	protected final int initComp;
    	protected final int visibleComp;
     
    	public AbstractComponent(int initComp, int visibleComp) {
    		super(new BorderLayout());
    		this.initComp=Math.max(0,initComp);
    		this.visibleComp=Math.min(initComp, visibleComp);
    	}
     
    	protected Dimension createPanel() {
    		JPanel conteneur = new JPanel(new GridBagLayout());
    		for(int i=0; i<initComp; i++) {
    			createChild(conteneur);
    		}
    		add(new JScrollPane(conteneur, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER),BorderLayout.CENTER);
     
    		JButton button = new JButton("Ajouter");
    		button.addActionListener(e-> addChild(conteneur));
    		add(button, BorderLayout.SOUTH);
    		Dimension dimension = button.getPreferredSize();
    		dimension.height+=getConteneurHeight(conteneur.getPreferredSize().getHeight(),getInsets());
    		return dimension;
    	}
     
    	private double getConteneurHeight(double height, Insets insets) {
    		int margin=insets.top+insets.bottom;
    		height-=margin;
    		height=(height/initComp)*visibleComp;
    		return height+margin;
    	}
     
    	private JComponent addChild(JPanel parent) {
    		JComponent child = createChild(parent);
    		child.revalidate();
    		SwingUtilities.invokeLater(()->child.scrollRectToVisible(child.getBounds()));
    		return child;
    	}
     
    	protected abstract C createChild(JPanel parent);
     
    }
    class Component extends AbstractComponent<JLabel> {
     
    	private final AtomicInteger ID = new AtomicInteger();
     
    	public Component(int initComp, int visibleComp) {
    		super(initComp, visibleComp);
    		Dimension dimension = createPanel();
    		setPreferredSize(dimension);
    		setMaximumSize(dimension);
    	}
     
    	protected JLabel createChild(JPanel parent) {
    		int y=ID.getAndIncrement();
    		JLabel label = new JLabel("Bidule "+(y+1));
    		parent.add(label, new GridBagConstraints(0, y, 1, 1, 1, /*un 1 ici aurait l'effet de "ratatinage"*/0, GridBagConstraints.BASELINE_LEADING, GridBagConstraints.HORIZONTAL, new Insets(2,1,2,1), 0, 0));
    		return label;
    	}
     
    }


    J'ai tout de même un peu du mal à voir l'interface finale que tu veux obtenir, mais je me demande si utiliser des JTable avec TableCellEditor spécifique ne serait pas plus simple.

Discussions similaires

  1. Réponses: 6
    Dernier message: 04/01/2011, 10h07
  2. [D2010] Ajout dynamique de composant dans un TGridPanel
    Par Djelangelo dans le forum Composants VCL
    Réponses: 2
    Dernier message: 07/12/2010, 16h49
  3. Ajout dynamique de label dans un panel avec scrollbar
    Par teddy_bear dans le forum Agents de placement/Fenêtres
    Réponses: 2
    Dernier message: 25/06/2009, 16h48
  4. Ajouter dynamiquement un composant dans un panel ou une popup
    Par ludogoal dans le forum Windows Presentation Foundation
    Réponses: 4
    Dernier message: 21/04/2008, 16h08
  5. [C#] Ajouter son propre composant dans Design de VS.Net
    Par yannick_sch dans le forum Windows Forms
    Réponses: 2
    Dernier message: 26/08/2004, 11h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo