Problème de redimensionnement de mon JPanel

Résolu
yoanpg Messages postés 156 Date d'inscription dimanche 15 février 2009 Statut Membre Dernière intervention 20 janvier 2024 - 27 nov. 2014 à 13:07
yoanpg Messages postés 156 Date d'inscription dimanche 15 février 2009 Statut Membre Dernière intervention 20 janvier 2024 - 1 déc. 2014 à 11:56
Bonjour à tous, :)
J'ai une classe étendant un JFrame, qui contient une méthode paint :
public void paint(Graphics g){
	accueil.setBounds(0, 0, accueil.getWidth(), accueil.getHeight());
	accueil.repaint();
	accueil.fenetre.setBounds(0, 0, accueil.getWidth(), accueil.getHeight());
	accueil.fenetre.repaint();
	System.out.println(accueil.fenetre.getWidth());
}


accueil est un objet de type Accueil, qui est une classe étendant un JPanel. Dans le constructeur de Accueil, je crée un JPanel appelé fenêtre.

Ce que je voudrais, c'est dès que je redimensionne ma JFrame, le accueil.fenetre soit automatiquement redimensionné à la taille maximale de la JFrame.
Ca marche quand je redimensionne "manuellement" (en étirant la fenêtre grâce à la flèche en bordure de fenêtre). Mais si je bascule entre le mode fenêtré et agrandi (avec le bouton de la barre de titre), ça ne fonctionne plus !!

Pourtant j'ai bien une ligne qui s'écrit dans la console avec la nouvelle taille, mais le JPanel fenetre ne se redimensionne pas. Et si je clique sur un élément du JPanel (JButton, JTextField ...) alors l'affichage se rétablit correctement.

Et c'est le même comportement si j'utilise un listener componentResized au lieu du paint.

Une idée d'où peut venir ce problème ?
Comment faire pour que le JPanel soit affiché à l'écran correctement lorsque je passe ma JFrame du mode fenêtré au mode plein écran ?
Est-ce qu'il y a quelque chose à ajouter dans mon JPanel accueil ? Ou dans le constructeur du JPanel fenetre ?

Merci de votre aide, car là je sèche ! :)
A voir également:

7 réponses

Twinuts Messages postés 5375 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 14 juin 2023 111
28 nov. 2014 à 11:50
Salut,

Quelques remarques:
- Faire un pack avant d'ajouter des composants n'a aucun sens. pack dimensionne la fenêtre en fonction de ce qu'il y a dedans.
- Faire pack puis setBounds n'a pas de sens, soit tu fais pack soit setBounds.

- Bien que je ne comprenne pas l'intérêt de cette méthode, dans la méthode afficher tu devrais essayer de revalider le conteneur:
public void afficher (JPanel afficher) {
  panel.removeAll();
  panel.add(afficher);
  panel.revalidate(); //  permet de reconstruire la taille et la position des composants au sein du LayoutManager 
  // panel.repaint(); // il se peut que l'appel du repaint soit nécessaire à voir.
}



1
Twinuts Messages postés 5375 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 14 juin 2023 111
28 nov. 2014 à 15:52
Salut,

Dans ce cas tu peux te servir d'un CardLayout qui sera plus propre au niveau des transitions entre l'agenda et l'accueil et surtout qui est fait pour ça.

exemple:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class Test extends JFrame implements ActionListener{
  private static final String CARD_HOME = "home";
  private static final String CARD_AGENDA = "agenda";
  /* je mets en globale pour le listener */
  private JPanel cards = null;
  
  public Test() {
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(300, 300);
    setLocationRelativeTo(null);
    
    /* pour le switch entre card */
    DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
    model.addElement(CARD_HOME);
    model.addElement(CARD_AGENDA);
    JComboBox<String> cbSwitch = new JComboBox<String>(model);
    cbSwitch.addActionListener(this);
    
    JPanel content = (JPanel)getContentPane();
    content.add(cbSwitch, BorderLayout.NORTH);
    
    /* panel contenant l'accueil et l'angenda */
    cards = new JPanel();
    cards.setLayout(new CardLayout());
    content.add(cards, BorderLayout.CENTER);
    
    /* l'accueil */
    JPanel panelAccueil = new JPanel();
    panelAccueil.setLayout(new BorderLayout());
    panelAccueil.add(new JButton("Bouton d'Accueil"));
    
    /* l'agenda */
    JPanel panelAgenda = new JPanel();
    panelAgenda.setLayout(new BorderLayout());
    panelAgenda.add(new JButton("Bouton d'Agenda"));
    
    
    cards.add(panelAccueil, CARD_HOME);
    cards.add(panelAgenda, CARD_AGENDA);
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    CardLayout cl = (CardLayout)(cards.getLayout());
    JComboBox<?> cb = (JComboBox<?>)e.getSource();
    // changement de carte
    cl.show(cards, cb.getSelectedItem().toString());
  }
  
  
  public static void main(String[] args) {
    new Test().setVisible(true);
  }

}


Plus de doc ici: https://docs.oracle.com/javase/tutorial/uiswing/layout/card.html

1
Twinuts Messages postés 5375 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 14 juin 2023 111
28 nov. 2014 à 09:51
Salut,

Bon plusieurs choses:
- En swing on ne dessine JAMAIS dans la méthode paint mais dans paintComponent
- On ne défini JAMAIS les tailles des composants dans un paint (ni même paintComponent)
- Utilise un LayoutManager pour gérer le redimensionnement automatique de tes composants*

*Exemple de Layout avec un panel qui s'adapte à la fenêtre:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class Test extends JFrame {
  
  
  public Test() {
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(new Dimension(300, 300));
    setLocationRelativeTo(null);
    
    
    JPanel content = (JPanel)getContentPane();
    content.setLayout(new BorderLayout());// layout par défaut du content pane

    // un panel qui sera au nord 
    addPanel(content, Color.WHITE, BorderLayout.NORTH, null);
    // un panel qui sera au centre 
    addPanel(content, Color.BLACK, BorderLayout.CENTER, null);
    // un panel qui sera au sud 
    addPanel(content, Color.RED, BorderLayout.SOUTH, null);
    // un panel qui sera à l'est 
    addPanel(content, Color.GREEN, BorderLayout.EAST, null);
    // un panel qui sera à l'ouest et avec une largeur préférentielle
    addPanel(content, Color.BLUE, BorderLayout.WEST, new Dimension(50, 0));
    
    // 
  }
  
  private static void addPanel(JPanel content, Color background, String position, Dimension preferredSize) {
    JPanel panel = new JPanel();
    panel.setBackground(background);
    if(preferredSize != null) panel.setPreferredSize(preferredSize);
    content.add(panel, position);
  }

  public static void main(String[] args) {
    new Test().setVisible(true);
  }
}


Il existe d'autres LayoutManager (officiels ou non)
https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html


0
yoanpg Messages postés 156 Date d'inscription dimanche 15 février 2009 Statut Membre Dernière intervention 20 janvier 2024 3
Modifié par yoanpg le 28/11/2014 à 11:14
Merci pour ta réponse.
Je ne comprends vraiment pas comment fonctionne ces Layout dans certains cas !!!!

J'ai fait quelques changements :
- Je n'ai finalement plus besoin de mon JPanel fenetre. Donc ma classe Accueil étend un JPanel avec un gridBagLayout dans lequel j'ajoute tous mes composants. De même, ma classe Agenda étend un JPanel avec un GridBagLayout qui contient tous mes composants.
- Dans ma classe Fenetre je fais :
public class Fenetre extends JFrame {
 private JPanel panel;
 Accueil accueil;
 Agenda agenda;

 public static void main(String[] args) {
  EventQueue.invokeLater(new Runnable() {
   public void run() {
    try {
     Fenetre frame = new Fenetre();
     frame.setVisible(true);
    } catch (Exception e) {
     e.printStackTrace();
    }
   }
  });
 }

 public Fenetre() {
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  pack();
  setBounds(100, 100, 1000, 600);
  setExtendedState(MAXIMIZED_BOTH);
  accueil = new Accueil(this);
  agenda = new Agenda(this);
  panel = (JPanel) getContentPane();
  panel.setLayout(new BorderLayout());
  panel.add(accueil);
 }
 
 public void afficher (JPanel afficher) {
  panel.removeAll();
  panel.add(afficher);
  panel.repaint();
  afficher.repaint();
 }
}


Dans chacune de mes classes Accueil et Agenda, j'ai un bouton qui appelle la méthode afficher(parent.agenda); ou afficher(parent.accueil); afin de basculer entre l'accueil et l'agenda (parent est un objet de type Fenetre, qui est récupéré en paramètre des constructeurs Accueil et Agenda).

Avec ces modifications, je n'ai plus de problème d'affichage lors du redimensionnement de ma fenêtre. Par contre, si j'affiche l'agenda (en cliquant sur le bouton correspondant dans l'accueil), puis que je diminue la fenêtre (l'agenda se redimensionne), puis je réaffiche l'accueil (avec le bouton correspondant dans l'agenda) alors mon JPanel accueil n'est pas redimensionné (il est resté à la taille plein écran), l'affichage est donc tronqué !

J'ai vraiment du mal à comprendre pourquoi des fois le JPanel se redimensionne tout seul, et d'autres fois non !
Une idée comment résoudre ce dernier petit point ?
Merci beaucoup ! :)
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
yoanpg Messages postés 156 Date d'inscription dimanche 15 février 2009 Statut Membre Dernière intervention 20 janvier 2024 3
28 nov. 2014 à 15:25
Merci pour les infos sur pack()
Et merci pour ta réponse, avec revalidate(), ça fonctionne !! :) Je ne connaissais pas cette méthode. Elle semble plus approprié que repaint().

Pour info, ma méthode afficher est appelée par des boutons dans Accueil et dans Agenda, afin de basculer l'affichage entre la page d'accueil et la page d'agenda (en chageant le JPanel affiché dans la JFrame).

Merci beaucoup de ton aide en tout cas, ça me sort une bonne épine du pied :)
0
yoanpg Messages postés 156 Date d'inscription dimanche 15 février 2009 Statut Membre Dernière intervention 20 janvier 2024 3
28 nov. 2014 à 16:08
Merci de l'info, je vais tester ça.
Je connaissais pas non plus. Il existe beaucoup d'éléments différents en Java !
0
yoanpg Messages postés 156 Date d'inscription dimanche 15 février 2009 Statut Membre Dernière intervention 20 janvier 2024 3
1 déc. 2014 à 11:56
Salut,
J'ai testé le CardLayout. En effet l'affichage est plus fluide.
Merci du tuyau :)
0
Rejoignez-nous