Partage
  • Partager sur Facebook
  • Partager sur Twitter

Utilisation d'une JTable

Utiliser une JTable avec des JButton.

Sujet résolu
    7 avril 2009 à 14:41:13

    Salut, alors j'ai lu le tutoriel de cysboy sur les JTable, mais j'ai quelque soucis surtout vers la fin du tutoriel.

    Alors, pour commencer la classe AbstractTableModel marche bien à une exception près : j'ai un problème quand je veux afficher les JCheckBox à la place des booléens :

    Voici le code donc que j'ai fait, c'est une table ou j'affiche toutes les locations de médias :

    package classes;
    
    import java.awt.Component;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.*;
    import javax.swing.table.*;
    
    public class LocationTable extends JFrame {	
    	private JTable table;
    	public LocationTable (Object[][] containing, String[] title) {
    		super("Locations");
    		TableModel model = new TableModel (title, containing);
    		table = new JTable (model);
    		table.getColumn("Accepter").setCellRenderer(new ButtonRenderer());
    		table.getColumn("Refuser").setCellRenderer(new ButtonRenderer());
    		table.getColumn("Accepter").setCellEditor(new ButtonEditor (new JCheckBox ()));
    		table.getColumn("Refuser").setCellEditor(new ButtonEditor (new JCheckBox ()));
    		
    		table.setRowHeight(30);
    		getContentPane ().add(new JScrollPane(table));
    		pack ();
    		setVisible(true);
    	}
    	//Fait le lien entre la JTable et l'utilisateur.
    	private class TableModel extends AbstractTableModel {
    		private String[] title;
    		private Object[][] containing;
    		//Reçois les données de la table.
    		private TableModel (String[] title, Object[][] containing) {
    			this.title = title;
    			this.containing = containing;
    		}
    		//Définis quelles sont les cellules éditables.
    		public boolean isCellEditable(int row, int col){
    			//On appelle la méthode getValueAt qui retourne la valeur d'une cellule
    			//Et on fait un traitement spécifique si c'est un JButton
    			if(getValueAt(0, col) instanceof JButton)
    				return false;
    			return true; 
    		}
    		
    		public Class getColumnClass(int col) {			
    			return  this.containing[0][col].getClass();			
    		}
    		public String getColumnName (int col) {
    			return this.title[col];
    		}
    		@Override
    		public int getColumnCount() {
    			// TODO Raccord de méthode auto-généré
    			return this.title.length;
    		}
    
    		@Override
    		public int getRowCount() {
    			// TODO Raccord de méthode auto-généré
    			return this.containing.length;
    		}
    
    		@Override
    		public Object getValueAt(int row, int col) {
    			// TODO Raccord de méthode auto-généré
    			return this.containing[row][col];
    		}
    		
    	}
    }
    

    Il m'indique un NullPointerException dans la méthode getColumnClass, pourtant, j'ai bien définis un nouveau type Boolean :
    ArrayList<Media> medias = Data.getMedia();
    			JFrame fenetreLocation = new JFrame ("Table of locations");
    			fenetreLocation.setLocationRelativeTo(null);
    			String[] title = new String[]{"Début", "Fin", "durée", "acceptée", "Pseudo du client", "Accepter", "Refuser"};
    			Object[][] locationsInfo = new Object[Location.getNbLocations()][7];
    			int i = 0;
    			if (!medias.isEmpty()) {
    				for (Media m : medias) {				
    					ArrayList<Location> locations = m.getLocations();
    					if (!locations.isEmpty()) {
    						for (Location l : locations) {
    							locationsInfo[i][0] = l.getDateDebut();
    							locationsInfo[i][1] = l.getDateLimit();
    							locationsInfo[i][2] = l.getDuree();
    							locationsInfo[i][3] = new Boolean (l.isAcceptee());
    							locationsInfo[i][4] = l.getClient().getName();
    							locationsInfo[i][5] = "Accepter";
    							locationsInfo[i][6] = "Refuser";						
    						}
    					}
    				}
    			}
    			new LocationTable (locationsInfo, title);
    


    Et vers la fin, je ne comprends pas très bien, enfin soit il a un truc qui me choque plutôt, c'est pourquoi on doit créer un nouveau JButton dans le constructeur de ButtonEditor, et aussi réaffiher le libellé sur le bouton hors que ça c'est déjà fait dans CellRenderer ?

    //Contrôle l'affichage des cellules.
    	private class ButtonRenderer extends JButton implements TableCellRenderer {
    		//Permet l'affichage des Boutons.
    		public Component getTableCellRendererComponent(	JTable table, Object value,
    														boolean isSelected, boolean isFocus,
    														int row, int col) {
    			//On écrit dans le bouton ce que contient la cellule
    			setText((value != null) ? value.toString() : "");
    			//on retourne notre bouton
    			return this;
    		}
    	}
    	//Gère l'édition de cellules. (Evènements sur des boutons, etc...)
    	private class ButtonEditor extends DefaultCellEditor {
    		protected JButton button;
    		private ButtonListener bListener = new ButtonListener ();
    		//On définis l'écouteur de nos bouton à la cellule de la table.
    		
    		public ButtonEditor (JCheckBox jcb) {
    			//Par défaut, cet objet utilise des JCheckBox.
    			super (jcb);
    			//On définit un nouveau bouton 
    			button = new JButton ();
    			button.setOpaque(true);
    			button.addActionListener(bListener);
    		}
    		public Component getTableCellEditorComponent(JTable table, Object value,
    				boolean isSelected, int row, int column) { 
    			//On définit le numéro de ligne à notre listener
    			bListener.setRow(row);
    			//Idem pour le numéro de colonne
    			bListener.setColumn(column);
    			//On passe aussi le tableau pour des actions potentielles
    			bListener.setTable(table);
    
    			//On réaffecte le libellé au bouton
    			button.setText( (value ==null) ? "" : value.toString() );
    			//On renvoie le bouton
    			return button;
    
    
    		}
    	}
    	private class ButtonListener implements ActionListener {
    		private int column, row;
    		private JTable table;
    		
    		public void setColumn(int col){this.column = col;}
    		public void setRow(int row){this.row = row;}
    		public void setTable(JTable table){this.table = table;}
    		@Override
    		public void actionPerformed(ActionEvent event) {
    			//On affiche un Zoli message mais vous pourriez faire les traitements que vous voulez
    			System.out.println("coucou du bouton : " + ((JButton) event.getSource()).getText() );			
    		}
    		
    	}
    }
    


    J'aime bien le Java pour sa simplicité de conception mais la je dois avouer que l'objet JTable n'est pas très pratique à utiliser surtout lorsqu'il y a des composants comme des boutons dedans!

    Là il ont pas fait simple sur ce coup là.
    • Partager sur Facebook
    • Partager sur Twitter
      8 avril 2009 à 10:33:28

      Ha je crois que j'ai enfin compris pourquoi il faut mettre deux fois le texte sur le bouton.
      TableCellRender ne gère que l'affichage des cellules non éditables.
      DefaultCellEditor ne gère que l'affichage et les actions lorsque la cellule est éditée. (Fiouf...)

      Par contre pour le remplacement des valeurs booléennes par les cases à cochés, je n'y arrive toujours pas.
      :'(

      Enfin soit pas grâve, c'est juste que mon appli sera disons, un peu moins jolie.





      • Partager sur Facebook
      • Partager sur Twitter
        12 mai 2009 à 14:10:14

        Voilà ça marche enfin, en fait pour remettre le l'affichage à jour fallait que j'appelle fireTableDataChanged ().
        Enfin voilà je mets le code donc :
        package classes;
        
        import java.awt.Component;
        import java.awt.event.ActionEvent;
        import java.awt.event.ActionListener;
        
        import javax.swing.*;
        import javax.swing.table.*;
        
        public class LocationTable extends JFrame {	
        	private JTable table;
        	
        	public LocationTable (Object[][] containing, String[] title) {
        		super("Table of locations");
        		
        		
        		table = new JTable (new TableModel (title, containing));		
        		
        		table.getColumn("Accepter").setCellRenderer(new ButtonRenderer());
        		table.getColumn("Refuser").setCellRenderer(new ButtonRenderer());
        		table.getColumn("Remit").setCellRenderer(new ButtonRenderer ());
        		table.getColumn("Accepter").setCellEditor(new ButtonEditor (new JCheckBox ()));
        		table.getColumn("Refuser").setCellEditor(new ButtonEditor (new JCheckBox ()));
        		table.getColumn("Remit").setCellEditor(new ButtonEditor (new JCheckBox ()));
        		
        		
        		table.setRowHeight(30);
        		
        		getContentPane ().add(new JScrollPane(table));
        		setSize(0, 1000);
        		pack ();
        		setResizable (false);
        		setVisible(true);
        	}
        	
        	//Fait le lien entre la JTable et l'utilisateur.
        	private class TableModel extends DefaultTableModel {
        				//Reçois les données de la table.
        		private TableModel (String[] title, Object[][] value) {
        			super (value, title);
        		}
        		//Définis quelles sont les cellules éditables.
        		public boolean isCellEditable(int row, int col){
        			//On appelle la méthode getValueAt qui retourne la valeur d'une cellule
        			//Et on fait un traitement spécifique si c'est un JButton
        			
        			if ((Boolean) getValueAt(row, 4)) {
        				if (table.getValueAt(row, col).equals("Remit")) 
        					return true;
        				else
        					return false;
        			} else {
        				if (table.getValueAt(row, col).equals("Remit"))
        					return false;
        				else
        					return true;
        			}
        		}		
        	}
        	
        	//Contrôle l'affichage des cellules.
        	private class ButtonRenderer extends JButton implements TableCellRenderer  {
        		//Permet l'affichage des Boutons.		
        		
        		public Component getTableCellRendererComponent(	JTable table, Object value,
        														boolean isSelected, boolean isFocus,
        														int row, int col) {	
        			
        			//On écrit dans le bouton ce que contient la cellule.
        			setText((value != null) ? value.toString() : "");
        			if ((Boolean) table.getValueAt(row, 4)) {	
        				
        				if (table.getValueAt(row, col).equals("Remit")) {					
        					setEnabled (true);
        				} else {
        					
        					setEnabled(false);
        				}				
        			} else {				
        				if (table.getValueAt(row, col).equals("Remit"))
        					setEnabled (false);
        				else
        					setEnabled(true);
        			}
        			
        			//on retourne notre bouton
        			return this;
        		}
        		public TableCellRenderer getCellRenderer (int row, int col) {
        			return getCellRenderer (row, col);
        		}
        	}
        	//Gère l'édition de cellules. (Evènements sur des boutons, etc...)
        	private class ButtonEditor extends DefaultCellEditor  {
        		protected JButton button;
        		
        		private ButtonListener bListener = new ButtonListener ();
        		//On définis l'écouteur de nos bouton à la cellule de la table.
        		
        		public ButtonEditor (JCheckBox jcb) {
        			//Par défaut, cet objet utilise des JCheckBox.
        			super (jcb);
        			//On définit un nouveau bouton 
        			button = new JButton ();
        			button.setOpaque(true);
        			button.addActionListener(bListener);
        		}
        		public Component getTableCellEditorComponent(JTable table, Object value,
        				boolean isSelected, int row, int column) { 
        			//On définit le numéro de ligne à notre listener
        			bListener.setRow(row);
        			//Idem pour le numéro de colonne
        			bListener.setColumn(column);
        			//On passe aussi le tableau pour des actions potentielles
        			bListener.setTable(table);
        
        			//On réaffecte le libellé au bouton
        			button.setText((value ==null) ? "" : value.toString() );
        			
        			//On renvoie le bouton
        			return button;
        		}
        		public void update () {
        			fireEditingStopped ();
        		}
        	}
        	private class ButtonListener implements ActionListener {
        		private int column, row;
        		private JTable table;
        		
        		public void setColumn(int col){this.column = col;}
        		public void setRow(int row){this.row = row;}
        		public void setTable(JTable table){this.table = table;}
        		
        		public void actionPerformed(ActionEvent event) {
        			 Media m = Data.getMediaByTitle((String) table.getValueAt(row, 6));
        			 Location l = m.getLocation((Integer) table.getValueAt(row, 0)); 
        			 Client c = l.getClient();			
        			 if (event.getActionCommand().equals("Accepter")) {	
        				 l.accepter();					 
        				 table.setValueAt(l.getDateDebut(), row, 1);
        				 table.setValueAt(l.getDateLimit(), row, 2);
        				 table.setValueAt(new Boolean (l.isAcceptee()), row,4);				 
        				 ((DefaultTableModel) table.getModel()).fireTableDataChanged();
        				 ((ButtonEditor) table.getCellEditor()).update();
        				 
        				 c.setMontantAPayer(l.getCost() + c.getMontant());									
        			 } else if (event.getActionCommand().equals("Refuser") || event.getActionCommand().equals("Remit")) {
        				 if (table.getModel().getRowCount() > 0) {						 
        					 ((DefaultTableModel) table.getModel ()).removeRow(row);
        					 if (event.getActionCommand().equals("Remit")) {
        						 c.setMontantAPayer(l.getCost() - c.getMontant());
        						 double montant = c.getMontant() - l.getCost();
        						 c.removeAmende(montant);
        					 }
        					 m.removeLocation(l);
        				 }
        			 }		 
        		}		
        	}	
        }
        


        Voilà je suis content que ça marche enfin!
        • Partager sur Facebook
        • Partager sur Twitter

        Utilisation d'une JTable

        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
        • Editeur
        • Markdown