web-dev-qa-db-fra.com

Comment contrôler dynamiquement les composants à redimensionnement automatique dans Java Swing

Création d'une nouvelle interface graphique en Java (1.8) Swing, je cherche un moyen de remplacer le comportement de redimensionnement de tous mes composants.

Laissez-moi vous expliquer avec quelques photos éditées:

1. Interface graphique plein écran

Ceci est mon interface graphique en plein écran, avec 3 panneaux et une JToolBar. Le vert doit avoir une taille fixe , les autres seraient redimensionnables .

Actuellement, je n'ai que 2 petits GridLayout pour les organiser (un vertical et un horizontal pour les panneaux verts et cyan).

FullScreen GUI

2. Petit redimensionnement horizontal

Si, par exemple, je réduisais la taille du cadre du côté droit, je voudrais que mes panneaux bleu et cyan soient redimensionnés en fonction de la nouvelle taille du cadre. Mais le panneau vert doit être corrigé . (Pas la partie la plus difficile, je pense.)

Resized once GUI

3. Taille horizontale minimale

C'est la partie la plus difficile pour moi. Dès que la taille du panneau cyan (ou bleu) est minimale, je souhaite qu’il " pousse le panneau vert " à gauche, même s’il disparaît du cadre.

Bien sûr, en tirant le cadre vers la droite, le panneau vert apparaîtra à nouveau.

Minimum size of the GUI

Comment pourrais-je le faire?

J'ai pensé à utiliser JSplitPane ou un auditeur spécifique pour décider manuellement du comportement de redimensionnement, mais j'ai besoin de conseils.

Désolé si un message existant peut répondre à cette question, je n'ai trouvé aucune réponse qui explique le problème pour moi.

Merci d'avance!


Si vous voulez plus d'exemples, regardez le logiciel "Evernote" qui agit de la même manière

12
Kapcash

La définition de la taille maximale/minimale/préférée du panneau Green permet de conserver la même taille dans le premier cas. Pour vérifier le redimensionnement, vous pouvez utiliser une ComponentListener sur l'une des autres JPanel - si la taille passe en dessous d'une largeur donnée, modifiez la taille maximale/minimale/préférée du panneau Green

Ci-dessous, vous trouverez un exemple de cela: il redimensionne le panneau Green lorsque Blue est <600, et le redimensionnement est un redimensionnement pondéré (30% de la largeur totale). Pour obtenir le vrai L & F et ce que vous désirez, vous devrez peut-être jouer avec la disposition/la taille. 

import Java.awt.BorderLayout;
import Java.awt.Color;
import Java.awt.Dimension;
import Java.awt.GridBagConstraints;
import Java.awt.GridBagLayout;
import Java.awt.GridLayout;
import Java.awt.Insets;
import Java.awt.Rectangle;
import Java.awt.event.ComponentAdapter;
import Java.awt.event.ComponentEvent;
import Java.awt.event.ComponentListener;

import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;


public class GridTest extends JPanel{

    private boolean changeAllowed = false;
    //keep reference to cyan for the height dimension
    final JPanel cyan = new JPanel();

    public GridTest(){
        cyan.setPreferredSize(new Dimension(600, 300));//provide sizing hint
    }

    private Dimension getCustomDimensions(){
        if ( changeAllowed ){
            return new Dimension((int)(super.getParent().getBounds().width * 0.3), cyan.getBounds().height);
        }else{
            return new Dimension(200, cyan.getBounds().height);
        }
    }
    @Override
    public Dimension getMaximumSize(){
        return getCustomDimensions();
    }
    @Override
    public Dimension getMinimumSize(){
        return getCustomDimensions();
    }
    @Override
    public Dimension getPreferredSize(){
        return getCustomDimensions();
    }

    public static void main(String[] args) throws Exception{
        SwingUtilities.invokeAndWait(new Runnable(){

            @Override
            public void run() {
                final int MINIMUM = 600;
                JFrame frame = new JFrame();
                frame.add(new JToolBar(), BorderLayout.NORTH);
                final JPanel blue = new JPanel();

                final GridTest green = new GridTest();
                green.setBackground(Color.green);
                green.setOpaque(true);

                green.cyan.setBackground(Color.cyan);
                green.cyan.setOpaque(true);
                blue.setOpaque(true);
                blue.setBackground(Color.blue);
                blue.setPreferredSize(new Dimension(900, 300));//hint at size
                blue.setMinimumSize(new Dimension(100, 200));//hint at size
                //Nest Box Layouts
                Box top = Box.createHorizontalBox();
                top.add(blue);
                Box bottom = Box.createHorizontalBox();
                bottom.add(green);
                bottom.add(green.cyan);
                Box vert = Box.createVerticalBox();
                vert.add(top);
                vert.add(bottom);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(vert);
                //listen for resizes
                blue.addComponentListener(new ComponentAdapter(){

                    @Override
                    public void componentResized(ComponentEvent e) {
                        if ( blue.getBounds().width < MINIMUM ){//set flag
                            green.changeAllowed = true;
                        }else{
                            green.changeAllowed = false;
                        }
                    }
                });

                frame.pack();
                frame.setSize(800, 600);
                frame.setVisible(true);

            }

        });
    }
}
7
copeg

Voici comment je le fais et je ne suis pas sûr que ce soit la bonne manière:

Commencez par définir la mise en page sur null.

Créez ensuite un événement de composant redimensionné pour votre cadre:

addComponentListener(new ComponentAdapter(){
            public void componentResized(ComponentEvent e){
            }
        });

À l'intérieur, vous pouvez modifier manuellement les composants à mesure qu'ils sont redimensionnés. Pour certains de mes programmes, j’ai fait en sorte que les volets de défilement à gauche et à droite du cadre aient toujours la même largeur et que tout le reste soit redimensionné et redimensionné.

3
Forseth11

Cela devrait être facile avec GridBagLayout, à condition de définir les tailles minimales appropriées pour les composants vert et cyan:

setLayout(new GridBagLayout());
green.setMnimumSize(new Dimension(0, 0));
cyan.setMinimumSize(new Dimension(100, 100)); // whatever fits
add(blue, new GridBagConstraints(0, 0, 2, 1,
        1.0, 0.0,
        GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
        new Insets(0, 0, 0, 0), 0, 0);
add(green, new GridBagConstraints(0, 1, 1, 1,
        0.0, 0.0,
        GridBagConstraints.WEST, GridBagConstraints.NONE,
        new Insets(0, 0, 0, 0), 0, 0);
add(cyan, new GridBagConstraints(1, 1, 1, 1,
        1.0, 0.0,
        GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
        new Insets(0, 0, 0, 0), 0, 0);

En spécifiant un poids x pour les composants cyan et bleu et en définissant redimensionner = HORIZONTAL, ils redimensionnent avec le conteneur.

3
Durandal

Vous pouvez utiliser une BoxLayout pour contenir les panneaux vert et cyan. Un BoxLayout respecte les tailles minimale et maximale d'un composant. Ainsi, pour le panneau vert que vous définissez, la taille maximale est égale à la taille préférée et pour le panneau cyan, la taille minimale est égale à la taille préférée:

import Java.awt.*;
import Java.util.*;
import javax.swing.*;

public class SSCCE extends JPanel
{
    public SSCCE()
    {
        JPanel blue = new JPanel();
        blue.setBackground( Color.BLUE );
        blue.setPreferredSize( new Dimension(500, 100) );

        Box box = Box.createHorizontalBox();

        JPanel green = new JPanel();
        green.setBackground( Color.GREEN );
        green.setPreferredSize( new Dimension(200, 100) );
        green.setMaximumSize( green.getPreferredSize() );
        box.add( green );

        JPanel cyan = new JPanel();
        cyan.setBackground( Color.CYAN );
        cyan.setPreferredSize( new Dimension(300, 100) );
        cyan.setMinimumSize( cyan.getPreferredSize() );
        box.add( cyan );

        setLayout( new BorderLayout() );
        add(blue, BorderLayout.NORTH);
        add(box, BorderLayout.CENTER);
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new SSCCE());
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
    }
}

Bien sûr, la solution appropriée consiste à remplacer les méthodes getMaximumSize() et getMinimumSize() respectivement de chaque panneau pour ne renvoyer que la taille préférée du panneau.

2
camickr

La séquence importante est la suivante:

                frame.revalidate();
                frame.pack();
                frame.repaint();
  1. revalidate (): invalide les composants jusqu'à la racine la plus proche, puis la composante hierarchy est validée à partir de la racine de validation la plus proche.
  2. pack (): la taille de la fenêtre est adaptée à la taille et à la présentation préférées de ses sous-composants. La largeur et la hauteur de la fenêtre résultantes sont automatiquement agrandies.
  3. repeint (): après tous ces calculs, le repeint montre les composants.

Utilisez cette séquence après chaque série de modifications que vous avez effectuées dans votre code et que vous souhaitez voir les résultats apparaître à l'écran.

J'aime le Java.awt.GridBagLayout en combinaison avec le Java.awt.GridBagConstraints et j'utilise cette présentation sur tous les conteneurs commençant à partir du volet contenu.

Si vous ajoutez un conteneur dans un autre conteneur, utilisez une présentation sur chacun d'eux, sinon le calcul échoue en raison d'une disposition manquante dans la hiérarchie.

0
michbau