IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

AWT/Swing Java Discussion :

creer un tableau avec des cellules divisees


Sujet :

AWT/Swing Java

  1. #1
    Nouveau candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Décembre 2017
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2017
    Messages : 1
    Par défaut creer un tableau avec des cellules divisees
    bonjour a tous,

    Je dois faire un petit exercice qui consiste en l'affichage des scores pour un bowling (le resultat que j'aimerais obtenie ressemble a la figure ci-dessous). Je n'ai pas de connaissances tres approfondies dans les interfaces graphiques en Java et ca fait plusieurs jours que je me tire les cheveux.

    Nom : Capture d'e?cran 2017-12-16 12.22.29.png
Affichages : 794
Taille : 28,3 Ko

    Voici les deux "solutions" auxquelles je suis arrivee mais soit je n'arrive pas l'implemente, soit la solution ne me satisfait pas completement:

    1) Je cree un JTable et pour les cellules de la 2/3 et 4/5 lignes, j'y mets un JPanel contenant 3 JLabel (2 au dessus pour les scores de chaque lance et un en dessous pour le score pour un frame). Je n'arrive pas a implemente cette solution. De ce que j'avais compris, il faudrait creer un objet qui "herite" de l'interface TableCellRenderer et definir la fonction public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column). Mais comment la redefinir pour voir mon JPanel comme je l'ai defini?

    Je me suis base sur ce site internet pour faire ceci mais, je n'ai pas bien compris comment la personne parvenait a afficher son JPanel dans la cellule de son JTable: https://www.pekalicious.com/blog/cus...tons-in-jtable

    2) J'essaye de cree moi-meme mon tableau a partir d'un JPanel en utilisant un GridBagLayout pour un maximum de flexibilite. Pour dessiner le tableau, j'utilise alors setBorder sur les differents JLabel. A ce moment la, je commence a avoir du chipotage dans le code pour avoir suffisamment d'espace pour chaque texte dans la cellule et que les lignes s'alignent correctement etc. De plus, c'est beaucoup moins flexible que d'utiliser un JTable.

    Est-ce que vous pourriez m'aider pour l'une ou l'autre maniere d'implementer un tableau comme je le voudrais ?

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Salut,

    La classe qui implémente TableCellRenderer sert à produire le dessin de l'intérieure d'une cellule :

    1. Il est important de se rendre compte qu'il ne s'agit pas d'un composant Swing à proprement parler, même si ça utilise des composants Swing pour faire le dessin. Cela signifie :
      1. lors du retour de l'appel de la méthode getTableCellRendererComponent, le dessin doit être prêt complètement, car c'est ce dessin qui apparaîtra dans la cellule. En taille, en disposition, et en valeur.
      2. qu'il est inutile de créer des composants dans getTableCellRendererComponent, comme fait dans l'exemple de ton lien. On les crée une fois pour toute, et on utilise les mêmes pour faire le dessin, ce qui économise du temps et de la mémoire.
        On les crée par exemple dans le constructeur de la classe qui implémente TableCellRenderer. La méthode getTableCellRendererComponent ne fera que remplir les composants pour afficher ce qu'on veut et de la manière qu'on veut (couleurs, tailles, etc...).
      3. Le corollaire est qu'il ne faut surtout pas considérer qu'il y des composants différents pour chaque cellule, puisque c'est bien le même qui sera utilisé.
      4. A noter qu'il faut retourner au plus un composant, qui constitue l'ensemble de la cellule, avec sa bordure. Tout l'intérieur peut être un simple dessin, pour le rendu du moins. S'il s'agit de pouvoir saisir les valeurs, c'est un tout autre problème, qui n'est pas du ressort du TableCellRenderer, mais du TableCellEditor.
    2. Le dessin d'un "tablecellrenderer" correspond à une valeur dans une cellule. Dans ton cas, comme il s'agit d'afficher trois informations, la valeur dans la cellule doit constituer ces 3 valeurs, en un seul objet. D'autres solutions sont possibles, mais constituent des contournements de la notion de JTable rendant inutile l'usage d'une JTable, voire risquant de provoquer des effets erratiques sur l'affichage, et ressemblent très vite à des usines à gaz.
    3. L'association entre un renderer et une valeur à afficher par ce renderer se fait
      • soit directement sur la colonne de la donnée (en passant par le modèle de colonnes)
      • soit par type, ce qui oblige
        • d'avoir le même type pour toutes les cellules
        • soit d'implémenter au minimum un modèle personnalisé avec la méthode getColumnClass()




    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    public class TableCellRendererExemple {
     
    	public static void main(String[] args) {
     
     
    		// je créé mes données :
    		String[] columns = new String[10]; // 10 colonnes0
    		for(int i=0; i<columns.length; i++) {
    			columns[i]="Col " + (i+1);
    		}
    		Object[][] data = new Object[10][columns.length]; // 10 lignes 
    		// je remplis aléatoirement
    		Random random = new Random();
    		for(Object[] ligne : data) {
    			for(int i=0; i<ligne.length; i++) {
    				ligne[i] = new TroisValeurs(random.nextInt(10),random.nextInt(10),random.nextInt(10)); 
    			}
    		}
     
    		// je créé l'instance de renderer
    		TableCellRenderer renderer = new TroisValeursRenderer();
     
    		// on crée un modèle juste pour pouvoir paramétrer la classe des valeurs
    		TableModel model = new DefaultTableModel(data, columns) {
    			@Override
    			public Class<?> getColumnClass(int columnIndex) {
    				return TroisValeurs.class;
    			}
    		};
     
    		// je créé la JTable
    		JTable table = new JTable(model);
    		table.setDefaultRenderer(TroisValeurs.class, renderer); // j'associer le renderer au type que je veux dessiner avec ce renderer
     
    		// une fenêtre pour l'affichage
    		JFrame frame = new JFrame("Démo");
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		// un panel pour afficher la JTable
    		JPanel panel = new JPanel(new BorderLayout());
    		panel.add(new JScrollPane(table));
    		panel.add(table.getTableHeader(), BorderLayout.NORTH);
    		frame.add(panel);
     
    		// affichage de la fenêtre
    		frame.pack();
    		frame.setLocationRelativeTo(null);
    		frame.setVisible(true);
     
     
    	}
     
    	public static class TroisValeursRenderer extends JPanel implements TableCellRenderer {
     
    		private JLabel jlabel1;
    		private JLabel jlabel2;
    		private JLabel jlabel3;
     
    		public TroisValeursRenderer() {
    			// pour afficher mes valeurs, je vais utiliser trois labels:
    			jlabel1 = new JLabel();
    			jlabel2 = new JLabel();
    			jlabel3 = new JLabel();
    			// un peu de décoration pour ces labels :
    			Border border = BorderFactory.createLoweredSoftBevelBorder();
    			decorate(jlabel1,border);
    			decorate(jlabel2,border);
    			decorate(jlabel3,border);
     
    			setLayout(new GridBagLayout()); // j'utilise un GridBagLayout pour la disposition des trois labels
    			GridBagConstraints gbc = new GridBagConstraints();
    			gbc.anchor=GridBagConstraints.CENTER; // on centre les jlabels
    			gbc.fill=GridBagConstraints.BOTH; // on demande au gridbaglayout que les jlabels s'étallent sur le maximum d'espace dans la grille (la taille du jlabel ne dépend plus du texte qu'il contient, mais de l'espace disponible, donné par la cellule de la JTable)
     
    			gbc.weightx=0.5f; // sur la première ligne, les deux composants vont se partager la largeur à 50/50
    			add(jlabel1,gbc);
     
    			gbc.gridx=1; // deuxième colonne de la première ligne
    			add(jlabel2,gbc);
     
    			gbc.gridx=0; // seconde ligne maintenant
    			gbc.gridwidth=2; // le jlabel de la seconde ligne s'étale sur les deux colonnes
    			gbc.gridy=1; // deuxième ligne
    			gbc.weightx=1f; // on s'étale au maximum de la largeur
    			add(jlabel3,gbc);
    		}
     
    		private void decorate(JLabel jlabel, Border border) {
    			jlabel.setOpaque(true);
    			jlabel.setBackground(Color.WHITE);
    			jlabel.setBorder(border);
    			jlabel.setHorizontalAlignment(SwingConstants.CENTER);
    		}
     
    		@Override
    		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
    				int row, int column) {
     
    			// ici on affecte les bonnes valeurs
    			TroisValeurs valeurs = (TroisValeurs)value;
     
                            // je place les valeurs dans les bons labels
    			jlabel1.setText(String.valueOf(valeurs.getValeur1()));
    			jlabel2.setText(String.valueOf(valeurs.getValeur2()));
    			jlabel3.setText(String.valueOf(valeurs.getValeur3()));
     
    			// je demande à Swing d'appliquer les règles de layout automatiquement
    			doLayout();
     
    			return this;
    		}
     
    	}
     
    	public static class TroisValeurs {
    		private int valeur1, valeur2, valeur3;
    		public TroisValeurs(int valeur1, int valeur2, int valeur3) {
    			this.valeur1=valeur1;
    			this.valeur2=valeur2;
    			this.valeur3=valeur3;
    		}
    		public int getValeur1() {
    			return valeur1;
    		}
    		public int getValeur2() {
    			return valeur2;
    		}
    		public int getValeur3() {
    			return valeur3;
    		}
    	}
     
     
    }
    Tu peux constater que le résultat est tout ratatiné. C'est parce qu'une JTable, habituellement, sert à afficher une donnée par ligne. Or, là, on en a deux. Il faut donc adapter. On peut tout simplement changer la taille des lignes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // je créé la JTable
    JTable table = new JTable(model);
    table.setDefaultRenderer(TroisValeurs.class, renderer); // j'associer le renderer au type que je veux dessiner avec ce renderer
     
    table.setRowHeight((int)(table.getRowHeight()*2.5));
    Ici, je dis que chaque ligne fait un peu près 2.5 fois la hauteur normale. 2.5 et pas 2, parce qu'il faut tenir compte des bordures de lignes.

    Il y a d'autres ajustements éventuels à faire pour que le TableCellRenderer se comporte exactement comme le renderer par défaut (pour les bordures relatives au focus par exemple). Tu trouveras dans ce forum d'autres exemples de TableCellRenderer (par exemple, ici, ici, ).

    Pour la première colonne, le nom des joueurs, tu peux utiliser une colonne dédiée, ou utiliser un "row header", ce qui te permettra de scroller la partie "points" en gardant la première colonne fixe (exemple dans le précédent lien, mais aussi ici).


    Maintenant, si tu veux aussi pouvoir saisir, il faudra aussi faire un TableCellEditor. N'hésite pas à demander des précisions si nécessaire, et commence par regarder cet exemple ici.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

Discussions similaires

  1. [WD-2010] Parcourir un tableau avec des cellules fusionnées
    Par Tanoffy dans le forum VBA Word
    Réponses: 0
    Dernier message: 09/12/2014, 14h05
  2. Réponses: 1
    Dernier message: 10/11/2014, 09h15
  3. Fonction de calcul avec des cellules de tableau HTML
    Par Gannox dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 24/09/2012, 07h28
  4. Réponses: 2
    Dernier message: 02/01/2012, 20h36
  5. Tableau avec des cellules imbriquées
    Par MonOncle dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 15/11/2006, 22h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo