Java : problème de JPanel

Fermé
Smith - 28 juin 2012 à 22:42
 Smith - 30 juin 2012 à 19:02
Bonjour, n'étant pas satisfait du JTabbedPane, j'ai décidé de créer mon propre gestionnaire d'onglets.
Le problème est que le changement d'onglet s'effectue mal, il marche 1 ou 2 fois et ne fonctionne plus en suite. Il n'y a ni boucle infinie, ni warning à la compilation ni exception pendant le traitement.

J'ai créer une classe qui extends JPanel et qui permet l'ajout de container avec une image.
L'image sert à créer le JPanel qui, lorsqu'il reçoit un event souris, change pour l'onglet qui lui correspond.
Je suis sûr que ma méthode n'est pas idéale, mais je n'ai pas trouvé mieux pour l'instant.


voici le code :

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

class OngletManager extends JPanel implements MouseListener
{
	private LinkedList<Container> onglets;
	private LinkedList<Container> save;
	private LinkedList<JLabel> labels;
	
	public int pos_x;
	public int pos_y;
	public int pas_x;
	public int pas_y;
	public int index;
	public int old_index;
	
	public void mouseExited(MouseEvent evt)
	{
	}
	public void mouseReleased(MouseEvent evt)
	{
	}
	public void mousePressed(MouseEvent evt)
	{
	}
	public void mouseEntered(MouseEvent evt)
	{
	}
	public void mouseClicked(MouseEvent evt)
	{
		int i =0;
		int max = labels.size();
		boolean ok = false;
		boolean end = false;
		
		System.out.println("\033[01;31m[Evènement Souris] \033[0m");
		
		
		while(!end && !ok)
		{
			if(evt.getSource() == labels.get(i))
				ok = true;
			else if(i>=max)
				end = true;
			else i++;
		}
			if(ok)
				setOnglet(i);
    }
    
    public OngletManager(int _x, int _y, int _pas_x, int _pas_y)
    {
		pos_x = _x;
		pos_y = _y;
		pas_x = _pas_x;
		pas_y = _pas_y;
		index = 0;
		old_index = -1;
		
		setLayout(null);
		onglets = new LinkedList<Container>();
		save = new LinkedList<Container>();
		labels = new LinkedList<JLabel>();
	}
	
	public void addOnglet(ImageIcon img, Container comp)
	{
		setLayout(null);		
		JLabel temp = new JLabel(img);		
		onglets.add(comp);
		save.add(comp);m
		labels.add(temp);
	}
	
	public void placeLabel()
	{
		
		int temp_x = pos_x;
		int temp_y = pos_y;
		
		System.out.println("placeLabel (index="+index+")");
		
		int a = 0;
		onglets.set(index, save.get(index));
		
		for(JLabel lab : labels)
		{			
				onglets.get(index).add(lab);
				lab.setBounds(temp_x, temp_y, lab.getIcon().getIconWidth(), lab.getIcon().getIconHeight());
				lab.removeMouseListener(this);
				lab.addMouseListener(this);
			
			temp_x += pas_x;
			temp_y += pas_y;
			a++;
		}
	}
	
	public void setOnglet(int _index)
	{
		System.out.println("SetOnglet("+_index+")");
		this.removeAll();
		this.setLayout(null);
		old_index = index;
		index = _index;		
		
		
		placeLabel();
		this.add(onglets.get(index));
		onglets.get(index).setBounds(0,0,1600,900);
		
	}
		 
}
A voir également:

3 réponses

KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
29 juin 2012 à 19:53
Alors je me suis plongé dans les profondeurs obscurs de ton code ^^

J'avoue que j'aurai beaucoup de chose à en dire, mais si je commence à modifier ton code, je changerai tout... ou presque !

Alors pour l'instant je vais juste te donner deux changements pour stabiliser ton code :

Dans placeLabel(), remplace cette ligne :
temp += pas_x;
Par celle-ci :
temp += pas_x+lab.getIcon().getIconWidth();
Et dans setOnglet(index), rajoute :

for (Component c : save)
	c.setVisible(false);

save.get(index).setVisible(true);
1
Merci, ça marche très bien, un peu long à lancer mais ça marche. Sinon, tu aurais quoi à en dire de mon code par exemple ? Histoire que j'en profites pour m'améliorer.
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
30 juin 2012 à 01:06
Un peu long à lancer ? Je n'ai rien remarqué... C'est peut-être à cause de tes images !

Sinon, il y a plein de choses qui ne servent à rien, ou que l'on pourrait enlever facilement.
old_index par exemple, tu ne t'en sers jamais. Tes trois listes à mon avis sont superflux, en fait tu hérites de JPanel mais sans te servir de ce qui existe déjà... et du coup ça fait doublon !

Globalement c'est ton architecture de classe que je trouve bancale.

Je pense que tu aurais intérêt à faire une classe pour les "labels images" qui sont tes onglets en soit, et une autre classe pour ton "Manager" mais qu'il faudrait scinder en deux : une barre avec tes onglets, et en dessous les contenus en soit. Pour l'instant le contenu se mélange aux onglets et c'est bizarre.

Enfin, tu l'as déjà mentionné, tu utilises le layout null, et c'est vrai que c'est moche, surtout à cause des mélanges d'onglets que j'ai mentionné...

Bref, comme je l'ai dit, moi je changerais quasiment tout ^^
0
Oui, mais justement, ça me paraît normal que les onglets se mélangent au contenu, je veux pouvoir mettre les boutons n'importe où dans l'affichage, que ce soit en plein milieu ou tout en haut, ce que ne permet pas le JTabbedPane. Je ne veux pas d'une barre d'onglet avec le contenu en dessous, ou au dessus..., le contenu doit pouvoir être autour des onglets. En fait je dirais que les boutons doivent juste être posés sur le contenu, qu'on ne puisse pas réellement distinguer de nuance entre le contenu et les onglets. Je sais pas si je me fais comprendre mais bon.
Après je t'ai peut être mal compris...
Sinon pour l'histoire du old_index je m'en suis servit au départ mais plus maintenant, c'était un oubli, je l'ai donc enlevé. Sinon j'ai remplacé le extends JPanel par extends Container, je sais pas si ça change grand chose mais en tout cas je suis obligé d'extends ça au minimum puisque j'utilise quand même quelques méthodes de Container.

Sinon ça se lance mieux depuis que j'ai remis tous les panneaux à leur place, mais bon de toute façon c'est du java donc pas le summum de la rapidité...
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
30 juin 2012 à 02:12
"le contenu doit pouvoir être autour des onglets."
Si je comprends bien, tu auras quand même deux zones distinctes, l'une avec les onglets, l'autre avec le contenu, et c'est en ça que je pense que tu aurais intérêts à scinder ton JPanel en deux. Après je proposais une coupure haut/bas pour me faire comprendre ce n'est pas l'essentiel.

"j'ai remplacé le extends JPanel par extends Container"
Effectivement ça ne changera pas grand chose puisque JPanel extends Container. Ce que je voulais dire au niveau de cet extends, c'est que tu ne te sers pas des méthodes qui existent déjà. Je pense en particulier au fait que les composants sont déjà stockés, et que tu peux les récupérer avec getComponents() par exemple, sans avoir à gérer des listes qui viennent alourdir le programme.

"de toute façon c'est du java donc pas le summum de la rapidité"
Beaucoup de gens pensent, que Java est lent donc ça ne sert à rien d'optimiser, car le programme sera toujours lent. Or c'est en n'optimisant pas que le programme devient lent. Un programme bien codé en Java sera meilleur qu'un programme mal codé en quelque autre langage...

Par exemple avec tes listes tu refais un traitement qui existe déjà, donc tu doubles inutilement ce traitement et le temps d'exécution, alors que tu pourrais totalement les supprimer...
Et je ne parle pas du fait que tu utilises des LinkedList alors qu'il serait plus rapide d'utiliser des ArrayList, car là on rentrerai vraiment dans de l'optimisation, et tu n'en es pas encore là !
0
Désolé si je suis chiant, mais j'aimerais bien comprendre pour apprendre de mes erreurs...
je ne vois pas ce que tu veux dire par le fait que mes composants soient déjà stockés, est-ce que ça signigie que je peux utiliser getComponent(int n) pour récupérer le n ième composant ajouté ? Et je définis quel onglet est actif avec setComponentZOrder ?
En tout cas merci de m'aider jusque là, j'ai appris le java en cours, mais c'est seulement le 2e projet que je code, le premier étant une déchetterie totale de code, et le reste étant des exercices beaucoup trop courts, j'ai voulu faire un nouveau projet plus propre pour coder mieux. Mais étant donné qu'aucun prof ne nous dit ce qu'il faut faire ou ne pas faire, c'est pas facile de trouver tout seul...
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
28 juin 2012 à 22:56
Salut !

Il y a un "m" qui se promène en plein milieu du code, et il faudrait que ta classe soit public.
Sinon, est-ce que tu aurais une classe de test que l'on puisse exécuter le code ?
0
Je vous fournis le code qui permet de tester, mais il faut des images pour pouvoir changer d'onglet, j'ai pas prévu de mode avec du texte car ça ne me servira pas.
ClassTest que je viens de faire :

import javax.swing.*;
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.*;
import java.awt.event.*;
import java.net.URL;
import java.util.*;

import java.awt.Dimension;

class ClassTest extends JPanel implements MouseListener
{

	public void mouseExited(MouseEvent evt)
	{
	}
	public void mouseReleased(MouseEvent evt)
	{
	}
	public void mousePressed(MouseEvent evt)
	{
	}
	public void mouseEntered(MouseEvent evt)
	{
	}
	public void mouseClicked(MouseEvent evt)
	{
	}

    public ClassTest()
    {
			setLayout(null);

			// création des onglets
			OngletManager onglets = new OngletManager(0,0,0,50);
			
			ImageIcon img3 = new ImageIcon("images/visuels/onglets/boutique.png");
			ImageIcon img = new ImageIcon("images/visuels/onglets/exploration.png");
			ImageIcon img2 = new ImageIcon("images/visuels/onglets/inventaire.png");

			
			JLabel txt1 = new JLabel("Panel1");
			JLabel txt2 = new JLabel("Panel2");
			JLabel txt3 = new JLabel("Panel3");

			
			JPanel onglet1 = new JPanel();
			
			JPanel onglet2 = new JPanel();
			
			JPanel onglet3 = new JPanel();
			
			onglet1.add(txt1);
			txt1.setBounds(400,400,200,60);
			onglet2.add(txt2);
			txt2.setBounds(400,400,200,60);
			onglet3.add(txt3);
			txt3.setBounds(400,400,200,60);
			
			
			onglets.addOnglet(img,onglet1);
			onglets.addOnglet(img2,onglet3);
			onglets.addOnglet(img3, onglet2);
			
			onglets.setOnglet(1);		
			

			onglets.setOpaque(false);
			add(onglets);
			onglets.setBounds(0,0,1600, 900);

    }
}



la Fenetre

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


class Fenetre extends JFrame {

		static ClassTest test1;
		
		private static final long    serialVersionUID    = 1L;

    public Fenetre()
    {   	
    	
		setTitle("Space String Adventures ALPHA");
		setPreferredSize(new Dimension(1600, 900));
		
		pack();
		test1 = new ClassTest();
		setContentPane(test1);
		
    }

}



et le Main :

import javax.swing.*;
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.*;
import java.awt.event.*;
import java.net.URL;
import java.util.*;

public class Main {

    static Fenetre fenetre;

    public static void main(String args[]) {

        fenetre = new Fenetre();
        fenetre.setVisible(true);
        fenetre.setLocationRelativeTo(null);
        fenetre.setResizable(false);
        fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}


PS : Oui, la moitié (voir plus) des import servent à rien (en tout cas pour l'instant) et je sais aussi que le positionnement en absolu avec layout(null) c'est pas beau mais si ça existe pourquoi ne pas s'en servir?

Bref. Sinon faut changer les images sinon les JLabels vont être invisibles, et on peut pas changer d'onglet.
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
28 juin 2012 à 23:59
Je regarderai le code de OngletManager demain, pour l'instant j'ai surtout défriché ta classe de test, et en fait on peux la simplifier pas mal, et se restreindre à ce code (plus c'est simple, mieux c'est)

import java.awt.Dimension;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Test
{
    private static void ajouter(OngletManager onglets, String fileImg, String txt)
    {
        ImageIcon img = new ImageIcon(fileImg);
        JLabel label = new JLabel(txt);
        label.setBounds(400,400,200,60);
        JPanel onglet = new JPanel();
        onglet.add(label);
        onglets.addOnglet(img, onglet);
    }

    public static void main(String[] args)
    {   
        OngletManager onglets = new OngletManager(0,0,0,50);

        ajouter(onglets,"images/visuels/onglets/boutique.png","Panel1");
        ajouter(onglets,"images/visuels/onglets/exploration.png","Panel2");
        ajouter(onglets,"images/visuels/onglets/inventaire.png","Panel3");
        
        onglets.setOnglet(1);            
        onglets.setOpaque(false);
        onglets.setBounds(0,0,1600, 900);
        
        JPanel panel = new JPanel();
        panel.setLayout(null);
        panel.add(onglets);
                
        JFrame fenetre = new JFrame();
        fenetre.setTitle("Space String Adventures ALPHA");
        fenetre.setPreferredSize(new Dimension(1600, 900));
        fenetre.add(panel);
        fenetre.pack();
        fenetre.setLocationRelativeTo(null);
        fenetre.setResizable(false);
        fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        fenetre.setVisible(true);
    }
}
0