Problème de redimensionnement de mon JPanel [Résolu]

yoanpg 124 Messages postés dimanche 15 février 2009Date d'inscription 18 mai 2017 Dernière intervention - 27 nov. 2014 à 13:07 - Dernière réponse : yoanpg 124 Messages postés dimanche 15 février 2009Date d'inscription 18 mai 2017 Dernière intervention
- 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 ! :)
Afficher la suite 

7 réponses

Répondre au sujet
Twinuts 5260 Messages postés dimanche 4 mai 2003Date d'inscriptionModérateurStatut 18 avril 2018 Dernière intervention - 28 nov. 2014 à 11:50
+1
Utile
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.
}



Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de Twinuts
Twinuts 5260 Messages postés dimanche 4 mai 2003Date d'inscriptionModérateurStatut 18 avril 2018 Dernière intervention - 28 nov. 2014 à 15:52
+1
Utile
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

Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de Twinuts
Twinuts 5260 Messages postés dimanche 4 mai 2003Date d'inscriptionModérateurStatut 18 avril 2018 Dernière intervention - 28 nov. 2014 à 09:51
0
Utile
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


Commenter la réponse de Twinuts
yoanpg 124 Messages postés dimanche 15 février 2009Date d'inscription 18 mai 2017 Dernière intervention - Modifié par yoanpg le 28/11/2014 à 11:14
0
Utile
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 ! :)
Commenter la réponse de yoanpg
yoanpg 124 Messages postés dimanche 15 février 2009Date d'inscription 18 mai 2017 Dernière intervention - 28 nov. 2014 à 15:25
0
Utile
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 :)
Commenter la réponse de yoanpg
yoanpg 124 Messages postés dimanche 15 février 2009Date d'inscription 18 mai 2017 Dernière intervention - 28 nov. 2014 à 16:08
0
Utile
Merci de l'info, je vais tester ça.
Je connaissais pas non plus. Il existe beaucoup d'éléments différents en Java !
Commenter la réponse de yoanpg
yoanpg 124 Messages postés dimanche 15 février 2009Date d'inscription 18 mai 2017 Dernière intervention - 1 déc. 2014 à 11:56
0
Utile
Salut,
J'ai testé le CardLayout. En effet l'affichage est plus fluide.
Merci du tuyau :)
Commenter la réponse de yoanpg

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.