JTabbedPane problème focus

Résolu
Hitsaki -  
KX Messages postés 19031 Statut Modérateur -
Bonjour à tous,

étant étudiant en licence informatique, j'ai décidé de crée un paint pour m'entrainer, j'ai donc respecter le schéma suivant :
- Une class Fenetre (extends JFrame) , elle contient un menu (via lequel on peut crée des nouveaux panneaux ainsi que l'Objet JTabbedPane (onglets)
- A chaque fois qu'on appuie sur "nouveau" pour un nouveau panneau, un onglet est crée , cet onglet contient une instance de Panneau (extends JPannel), qui lui meme contient des boutons pour le choix de la couleur de dessins, quelques outils, ainsi qu'une zone de dessin ( Class Draw, extends JPannel, implements mouse listener).
Donc on crée une fenetre, puis quand on crée un nouveau projet, cela crée un panneau qui lui meme contient des boutons et un Draw.
Tout marche niquel sur le paint, mais :

Mon problème est le suivant, quand je lance le programme : Je crée un onglet , je peux dessiner dessus. Je recrée un onglet, la le focus passe sur le DERNIER onglet crée, MEME SI je reviens sur le premier onglet (et j'ai bien vérifier qu'il comprend bien que j'y suis) il dessine sur le Draw du DERNIER ONGLET OUVERT et cela peut importe le nombre d'onglets ouvert, j'ai donc essayer de stocké tout les panneau (onglets) dans un tableau pour ensuite donner le focus a celui sur lequel je vais me rendre (avec tabpan[onglets.getSelectedIndex()].requestFocusInWindow(); ) (j'ai aussi essayer de donner le focus a la Draw avec tabpan[onglets.getSelectedIndex()].getDraw().requestFocusInWindow();

mais sans succès. Je ne comprend pas pourquoi quoi que je fasse, meme quand je suis sur un autre onglet les points de touts les onglets s'affiche bien (si je dessine un A sur le premier, puis un B sur le deuxieme quand je switch entre les deux il m'affiche bien un coup A un coup B) mais une fois que j'ai deux onglets ou plus il dessine uniquement sur le dernier. je met ici le code de la classe Fenetre, faites moi signe si vous voulez les autres classes. Merci par avance

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class Fenetre extends JFrame {

private Panneau [] tabpan = new Panneau [2000];
JTabbedPane onglets;
//private Panneau pan; // panneau principal de l'appli
private static int compt = 0;

public Fenetre () {
this.setTitle("Paint"); // titre fenetre
this.setSize(900,700); // taille fenetre
this.setMinimumSize(new Dimension (900,700)); // taille minimum possible de la fenêtre
//this.setLocationRelativeTo(null); // positionement fenetre au centre
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // quitte processus quand on ferme fenetre
//pan = new Panneau(); // crée le panneau principal de la fenetre ou on mettera les composants
onglets = new JTabbedPane();
onglets.addChangeListener(new Change());
//JButton close = new JButton ("x");
//close.addActionListener(new Close());
//onglets.addTab("Image " + compt, null, pan,null);
JMenuBar barre = new JMenuBar ();
JMenu fichier = new JMenu ("Fichier");
JMenuItem nouveau = new JMenuItem ("Nouveau");
nouveau.addActionListener(new ActionPan());
fichier.add(nouveau);
barre.add(fichier);
this.setJMenuBar(barre);
setContentPane(onglets);
//this.setContentPane(onglets); // inclus le panneau crée dans la fenetre
this.setVisible(true); // rend la fenêtre visible
//pan.repaint(); // appel la methode paintComponent() héritée de JPanel
}

public static void main(String[] args) {
Fenetre paint = new Fenetre (); // crée la fenetre principale
}

class ActionPan implements ActionListener {
public void actionPerformed(ActionEvent arg0) {
tabpan[compt] = new Panneau();
onglets.addTab("Image " + (compt+1), null, tabpan[compt],null);
compt++;
}
}

class Change implements ChangeListener {
public void stateChanged(ChangeEvent event){
tabpan[onglets.getSelectedIndex()].requestFocusInWindow();
//tabpan[onglets.getSelectedIndex()].getDraw().requestFocusInWindow();
}
}

// window adapter pour fermer la fenêtre quand on clique sur la croix rouge
class Fermer extends WindowAdapter {
public void windowClosing (WindowEvent evt) {
evt.getWindow().dispose();
System.exit(0);
}
}
}

1 réponse

  1. KX Messages postés 19031 Statut Modérateur 3 020
     
    Bonjour,

    On n'a pas la classe Panneau pour pouvoir reproduire ton problème.
    Est-ce que tu pourrais nous fournir un code complet pour tester ?

    PS. Panneau[2000] c'est violent, tu penses vraiment utiliser 2000 onglets en même temps ? Ici il te faudrait plutôt une liste qu'un tableau, ça te permettra d'avoir autant d'onglets que tu veux même si tu ne sais pas combien tu peux en avoir au maximum.
    0
    1. Hitsa Messages postés 2 Statut Membre
       
      Salut merci de ta réponse, je comptais effectivement utiliser ArrayList<Panneau> la c'était juste pour le test, je te laisse les autre classes :

      import java.awt.*;
      import java.awt.event.*; // action listener
      import javax.swing.*;
      import javax.swing.event.*;
      import java.util.*;

      public class Panneau extends JPanel{

      private static Draw draw;
      private JComboBox curseur;
      private MyButton gomme;
      private MyButton crayon;

      // ce constructeur crée et organise le Panneau principal dans lequel on place tout les éléments
      public Panneau () {
      setBackground(Color.lightGray);
      setLayout(new GridBagLayout());
      // paramètres du composant Draw (zone de dessin)
      draw = new Draw (); // declaration panel
      draw.addMouseListener(new Mouse());
      draw.addMouseMotionListener(new Mouse());
      draw.setPreferredSize(new Dimension(700, 500)); // taille préférée
      draw.setBackground(Color.white); // couleur
      GridBagConstraints gbc = new GridBagConstraints(); // créations des contraintes
      gbc.gridx = gbc.gridy = 0; // placement dans la grille
      gbc.gridwidth = 1;
      gbc.gridheight = 2;
      gbc.fill = GridBagConstraints.BOTH; // redimensionnement quand fenetre s'aggrandit
      gbc.weightx = gbc.weighty = 1.0;
      gbc.insets = new Insets(20, 20, 10, 20); // marges autour
      gbc.gridwidth = GridBagConstraints.RELATIVE; // avant dernier de sa ligne
      gbc.gridheight = 2;
      add(draw,gbc); // ajout de la barre de couleurs

      // paramètres du composant couleur
      Panel couleurs = new Panel ();
      couleurs.setPreferredSize(new Dimension(80, 250));
      couleurs.setBackground(Color.lightGray);
      GridBagConstraints gbc2 = new GridBagConstraints();
      gbc2.gridx = 1;
      gbc2.gridy = 1;
      gbc2.insets = new Insets(0, 0, 20, 20); // marges
      gbc2.gridheight = 1;
      gbc2.gridwidth = GridBagConstraints.REMAINDER; // dernier de sa ligne
      add(couleurs, gbc2);

      // on ajoute la zone de séléction des outils
      Panel outils = new Panel ();
      outils.setPreferredSize(new Dimension(80, 300));
      outils.setBackground(Color.gray);
      GridBagConstraints gbc3 = new GridBagConstraints();
      gbc3.gridx = 1;
      gbc3.gridy = 0;
      gbc3.insets = new Insets(20,0,10,20); // marges autours
      gbc3.fill = GridBagConstraints.VERTICAL; // s'étend verticalement si fenetre grandit
      gbc3.gridwidth = GridBagConstraints.REMAINDER; // dernier de sa ligne
      gbc3.gridheight = 1;
      add(outils, gbc3);

      // ajout de la selection de curseur dans les outils
      JLabel labComb = new JLabel("Curseur :");
      labComb.setForeground(Color.black); // couleur du texte
      outils.setLayout(new FlowLayout());
      outils.add(labComb);
      curseur = new JComboBox();
      curseur.addActionListener(new ActionComb());
      curseur.addItem("Rond");
      curseur.addItem("Carré");
      outils.add(curseur);

      // on ajoute la zone de selection de taille
      JSlider taille = new JSlider(); // slider pour séléctionner la taille
      taille.setPreferredSize(new Dimension(65, 10));
      taille.setMinimum(1); // min de selection
      taille.setMaximum(400); // max de selection
      taille.setValue(30); // valeur par défaut
      JLabel labtaille = new JLabel ("Cuseur taille : " + taille.getValue() + " px"); // label accompagnant la séléction
      labtaille.setForeground(Color.black);
      taille.addChangeListener(new ChangeListener(){ // ajout du listener pour afficher la taille en live
      public void stateChanged(ChangeEvent event){
      labtaille.setText("Curseur taille : " + taille.getValue() + "px");
      draw.setCurseurWidth(taille.getValue());
      }
      });
      GridBagConstraints gbc4 = new GridBagConstraints(); // contraintes slider
      gbc4.gridx = 0;
      gbc4.gridy = 2;
      gbc4.gridwidth = GridBagConstraints.REMAINDER; // dernier de sa ligne
      gbc4.gridheight = 1;
      gbc4.anchor = GridBagConstraints.LINE_START; // il reste a gauche
      gbc4.insets = new Insets(0, 20, 2, 0); // marge
      outils.add(taille, gbc4); // ajout au panel

      // on ajoute le label "outils" dans outils
      JLabel laboutils = new JLabel ("Outils :");
      laboutils.setForeground(Color.black);
      outils.add(laboutils);

      // on ajoute la gomme
      gomme = new MyButton ("boutons/gomme.png", "boutons/gommeap.png");
      gomme.addActionListener(new Action());
      gomme.setPreferredSize(new Dimension(30,30));
      outils.add(gomme);

      // on ajoute le crayon
      crayon = new MyButton ("boutons/crayon.png", "boutons/crayonap.png");
      crayon.addActionListener(new Action());
      crayon.setPreferredSize(new Dimension(30,30));
      outils.add(crayon);

      // label avec la taille
      GridBagConstraints gbc5 = new GridBagConstraints(); // contraintes du label
      gbc5.gridx = 0;
      gbc5.gridy = 3;
      gbc5.gridwidth = GridBagConstraints.REMAINDER; // dernier de sa ligne
      gbc5.gridheight = GridBagConstraints.REMAINDER; // dernier de sa colonne
      gbc5.anchor = GridBagConstraints.LINE_START; // il reste a gauche
      gbc5.insets = new Insets(0, 20, 20, 0); // marge
      add(labtaille, gbc5); // ajout au panel

      // on crée et ajoute les couleurs dans la zone de couleurs
      couleurs.setLayout(new GridLayout(6,2));
      JButton black = new JButton ("black");
      black.addActionListener(new Action ());
      black.setForeground(Color.white);
      black.setBackground(Color.black);
      couleurs.add(black);
      JButton gray = new JButton("gray");
      gray.addActionListener(new Action ());
      gray.setBackground(Color.gray);
      couleurs.add(gray);
      JButton orange = new JButton("orange");
      orange.addActionListener(new Action ());
      orange.setBackground(Color.orange);
      couleurs.add(orange);
      JButton yellow = new JButton("yellow");
      yellow.addActionListener(new Action ());
      yellow.setBackground(Color.yellow);
      couleurs.add(yellow);
      JButton blue = new JButton("blue");
      blue.addActionListener(new Action ());
      blue.setBackground(Color.blue);
      couleurs.add(blue);
      JButton green = new JButton("green");
      green.addActionListener(new Action ());
      green.setBackground(Color.green);
      couleurs.add(green);
      JButton pink = new JButton("pink");
      pink.addActionListener(new Action ());
      pink.setBackground(Color.pink);
      couleurs.add(pink);
      JButton cyan = new JButton("cyan");
      cyan.addActionListener(new Action ());
      cyan.setBackground(Color.cyan);
      couleurs.add(cyan);
      JButton lightGray = new JButton("lightGray");
      lightGray.addActionListener(new Action ());
      lightGray.setBackground(Color.lightGray);
      couleurs.add(lightGray);
      JButton red = new JButton("red");
      red.addActionListener(new Action ());
      red.setBackground(Color.red);
      couleurs.add(red);
      JButton darkGray = new JButton("darkGray");
      darkGray.addActionListener(new Action ());
      darkGray.setBackground(Color.darkGray);
      couleurs.add(darkGray);
      JButton magenta = new JButton("magenta");
      magenta.addActionListener(new Action ());
      magenta.setBackground(Color.magenta);
      couleurs.add(magenta);
      }

      public Draw getDraw () {
      return draw;
      }

      class MyButton extends JButton {
      private static final long serialVersionUID = 1L;
      public MyButton(String icon, String iconHover) {
      super("");
      setContentAreaFilled(false); // On met à false pour empêcher le composant de peindre l'intérieur du JButton.
      setBorderPainted(false); // De même, on ne veut pas afficher les bordures.
      setFocusPainted(false); // On n'affiche pas l'effet de focus.
      setIcon(new ImageIcon(icon));
      setRolloverIcon(new ImageIcon(iconHover));
      }
      }


      // ------------------------------ LISTENERS DES DIFFERENTS ELEMENTS --------------------------------------------

      // gère les boutons de couleurs
      class Action implements ActionListener {
      public void actionPerformed (ActionEvent evt) {
      String etiquette = evt.getActionCommand(); // recupère l'étiquette du bouton appuyé
      // la compare une a une au boutons couleurs :
      if (etiquette.equals("black"))
      draw.setCol(Color.black);
      else if (etiquette.equals("gray"))
      draw.setCol(Color.gray);
      else if (etiquette.equals("orange"))
      draw.setCol(Color.orange);
      else if (etiquette.equals("yellow"))
      draw.setCol(Color.yellow);
      else if (etiquette.equals("blue"))
      draw.setCol(Color.blue);
      else if (etiquette.equals("green"))
      draw.setCol(Color.green);
      else if (etiquette.equals("pink"))
      draw.setCol(Color.pink);
      else if (etiquette.equals("cyan"))
      draw.setCol(Color.cyan);
      else if (etiquette.equals("lightGray"))
      draw.setCol(Color.lightGray);
      else if (etiquette.equals("red"))
      draw.setCol(Color.red);
      else if (etiquette.equals("darkGray"))
      draw.setCol(Color.darkGray);
      else if (etiquette.equals("magenta"))
      draw.setCol(Color.magenta);
      // compare a la gomme :
      else if (evt.getSource().equals(gomme))
      draw.setCol(Color.white);
      // compare au crayon :
      else if (evt.getSource().equals(crayon))
      draw.setCol(Color.black);
      }
      }

      // gère les cliques de la souris
      class Mouse implements MouseListener, MouseMotionListener {
      // quand on clic une fois sur le clic gauche
      public void mouseClicked (MouseEvent evt) {
      draw.execute(evt.getX(), evt.getY());
      repaint();
      }
      public void mouseEntered (MouseEvent evt) {}
      public void mouseExited (MouseEvent evt) {}
      public void mousePressed (MouseEvent evt) {}
      public void mouseReleased (MouseEvent evt) {}

      public void mouseMoved(MouseEvent e) {}

      // quand le clique gauche reste appuyer
      public void mouseDragged(MouseEvent e) {
      draw.execute(e.getX(), e.getY());
      repaint();
      }
      }

      // gère le choix de la forme du curseur
      class ActionComb implements ActionListener {
      public void actionPerformed (ActionEvent e) {
      String result = (String) curseur.getSelectedItem();
      draw.setCurseur(result);
      }
      }
      }


       import java.awt.*;
      import java.awt.event.*; // action listener
      import javax.swing.*;
      import java.awt.image.*;

      public class Draw extends JPanel {

      // curseur :
      private Color curseurCol; // couleur du curseur
      private String curseur; // forme du curseur
      private int curseurWidth; // largeur du curseur

      // Points :
      private ColorPoint [] frame; // tableau contenant tout les points du dessin
      private int coord; // sauvegarde du prochain index du tableau


      public Draw () {
      frame = new ColorPoint [2000000];
      curseurCol = Color.black;
      coord = 0;
      curseurWidth = 30;
      curseur = "Rond";
      Cursor curs = creerCurseur();
      this.setCursor(curs);
      }

      // méthode héritée, elle sert à peindre tout ce que contiendra le pannel, on l'appel a chaque changement via draw.repaint()
      public void paintComponent (Graphics g) {
      g.setColor(Color.white); // on repaint le fond en blanc
      g.fillRect(0,0,(int)getSize().getWidth(), (int)getSize().getHeight()); // repeinte
      for (int i = 0; i < frame.length; i++) { // affiche tout les points un par un
      if (frame[i] != null) {
      g.setColor(frame[i].getCol()); // prend la couleur du point a afficher
      if (frame[i].getCurseur().equals("Carré"))
      g.fillRect(frame[i].getX(), frame[i].getY(), frame[i].getWidth(), frame[i].getWidth()); // affiche le point
      else if (frame[i].getCurseur().equals("Rond"))
      g.fillOval(frame[i].getX(), frame[i].getY(), frame[i].getWidth(), frame[i].getWidth()); // affiche le point
      }
      }
      }

      // change la couleur du curseur puis actualise le curseur
      public void setCol (Color col) {
      curseurCol = col;
      Cursor curs = creerCurseur();
      setCursor(curs);
      }

      // change la taille du curseur puis actualise le curseur
      public void setCurseurWidth (int x) {
      curseurWidth = x;
      Cursor curs = creerCurseur();
      setCursor(curs);
      }

      // change la forme du curseur puis actualise le curseur
      public void setCurseur (String curs) {
      curseur = curs;
      Cursor curs1 = creerCurseur();
      setCursor(curs1);
      }

      // créer un nouveau curseur en fonction de la taille, de la couleur, et de la forme
      public Cursor creerCurseur () {
      BufferedImage image = new BufferedImage(curseurWidth,curseurWidth, BufferedImage.TYPE_INT_ARGB);
      Graphics g = image.getGraphics();
      g.setColor(curseurCol);
      if (curseur.equals("Rond"))
      g.fillOval(0,0, curseurWidth, curseurWidth);
      else if (curseur.equals("Carré"))
      g.fillRect(0,0, curseurWidth, curseurWidth);
      return Toolkit.getDefaultToolkit().createCustomCursor(image, new Point(curseurWidth/2,curseurWidth/2), "curseur perso");
      }

      // méthode appeler pour enregistrer un nouveau point dans le tableau de ColorPoint
      public void execute (int x, int y) {
      frame[coord] = new ColorPoint(x-curseurWidth/2, y-curseurWidth/2, curseurCol, curseurWidth, curseur); // met le point dans le tableau
      coord ++; // augmente la coordonnée du tableau pour le point suivant
      }
      }


       import java.awt.*;
      public class ColorPoint {
      private Color couleur;
      private int x;
      private int y;
      private int width;
      private String curseur;

      public ColorPoint (int x, int y, Color color, int w, String curs) {
      couleur = color;
      this.x = x;
      this.y = y;
      width = w;
      curseur = curs;
      }

      //retour X point
      public int getX () {
      return x;
      }

      // retour Y point
      public int getY () {
      return y;
      }

      // retour forme du point
      public String getCurseur() {
      return curseur;
      }

      // retour largeur du point
      public int getWidth() {
      return width;
      }

      // retour couleur curseur
      public Color getCol() {
      return couleur;
      }

      }


      merci par avance !
      0
    2. KX Messages postés 19031 Statut Modérateur 3 020
       
      Ce n'est pas grand chose, une petite erreur d'étourderie facile à corriger (mais qui coûte très cher en débogage parce que ce n'est pas évident à trouver).

      public class Panneau extends JPanel{
      
      	private static Draw draw; // draw ne doit pas être static !
      0
    3. Hitsa Messages postés 2 Statut Membre > KX Messages postés 19031 Statut Modérateur
       
      oh mon dieu....... je n'aurai jamais trouvé, tu me sauves, dire qu'hier j'ai passer plus de 6h la dessus j'étais a deux doigts de devenir fou aha, merci beaucoup à toi ! a + (je met en resolu)
      0
    4. KX Messages postés 19031 Statut Modérateur 3 020 > KX Messages postés 19031 Statut Modérateur
       
      Remarque : je trouve ton code assez compliqué, en particulier je pense que ton
      ColorPoint[] frame
      est une mauvaise idée (très structurante pour ton programme).

      Il aurait été plus simple de manipuler directement un BufferedImage, via sa méthode getGraphics() et de le réafficher au fur et à mesure de ses modifications.

      Exemple :

      public static void main(String[] args) {
          BufferedImage img = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
          Graphics graph = img.getGraphics();
          graph.setColor(Color.RED);
      
          Container draw = new Container() {
              public void paint(Graphics g) {
                  g.drawImage(img, 0, 0, this);
              }
          };
      
          draw.addMouseListener(new MouseAdapter() {
              public void mouseClicked(MouseEvent e) {
                  graph.fillRect(e.getX(), e.getY(), 5, 5);
                  draw.repaint();
              }
          });
      
          JFrame frame = new JFrame();
          frame.setSize(500, 500);
          frame.setContentPane(draw);
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.setVisible(true);
      }
      0
    5. Hits > KX Messages postés 19031 Statut Modérateur
       
      je vais tester ca j'y avais pas penser mais ca a l'air mieux oui ! merci
      0