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:
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).
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.)
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.
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
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);
}
});
}
}
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é.
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.
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.
La séquence importante est la suivante:
frame.revalidate();
frame.pack();
frame.repaint();
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.