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

Composants Java Discussion :

[JTable] problème sélection / event


Sujet :

Composants Java

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 32
    Points : 22
    Points
    22
    Par défaut [JTable] problème sélection / event
    Bonjour,


    Je développe actuellement une JTable très spécifique destinée à de la saisie de masse, et j'ai bien du mal avec les interractions.
    Ma table possède un Renderer, un Editor, un TableModel faisant référence a des tableaux spéciaux, affiche des objets complexes, ajoute des lignes vides, possède un header de colonne mais aussi de ligne, bref je commence a m'y perdre ...


    Pour le moment, l'acquisition des données est ok, et ma table s'affiche correctement. Mon soucis se situe au niveau des sélections et des évenments.
    J'aimerais pouvoir spécifier moi meme le comportement des selections, à savoir:

    - en fin de tableau, sur appui de touche enter ou tab, ajout d'une ligne vide ( ca c'est fait) puis selection de la 1ere cellule editable de cette nouvelle ligne. Probleme: l'event de la touche s'effectue apres l'ajout de ligne, et donc mon changeSelection() est faux. peut on "annuler" l'event levé par la touche?

    - empecher la sélection automatique des cellules non editables, que la selection passe directement a la prochaine cellule editable.

    - par contre un double click sur une cellule d'entete de ligne (cellule non editable) doit pouvoir permettre la selection de la ligne entiere



    Est ce que tout ceci est parametrable via un addListSelectionListener (), dois-je créer une nouvelle classe SelectionListener, et sur quel objet dois-je travailler (JTable, Renderer, Editor, Model, ..)??


    Grand merci à ceux qui voudrons bien me répondre

  2. #2
    Membre émérite
    Avatar de xavlours
    Inscrit en
    Février 2004
    Messages
    1 832
    Détails du profil
    Informations forums :
    Inscription : Février 2004
    Messages : 1 832
    Points : 2 410
    Points
    2 410
    Par défaut
    Bonjour,

    le comportement de la JTable lorsqu'on appuie sur Entrée ou sur Tab est défini dans le LookAndFeel avec des KeyBindings.

    Pour modifier le comportement de la JTable sur les touches entrée et tab, tu peux créer une nouvelle clé dans l'InputMap ou réutiliser celle qui existe déjà :
    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
    InputMap im = maJTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
     
    // créer une nouvelle clé
    Object key = "mon action entrée";
    assert !im.contains(key);
    im.put(KeyStroke.getKeyStroke("Enter"), key);
     
    //ou bien utiliser la même clé
    Object key = 
    im.get(KeyStroke.getKeyStroke("Enter"));
     
    // dans les 2 cas
    maJTable.getActionMap().put(key, new EnterAction);
     
    ...
    class EnterAction extends AbstractAction {
     
      private void selectNextEditableCell(JTable table) {
        // créer une nouvelle ligne si nécessaire
        ...
      }
     
      public void actionPerformed(ActionEvent e) {
        JTable table = (JTable) e.getSource();
        selectNextEditableCell(table);
      }
    }
    Pour le double clic, un MouseListener qui utilise les méthodes MouseEvent#getPoint(), MouseEvent#getClickCount(), JTable#columnAtPoint() et JTable.rowAtPoint() devrait te permettre de faire tout ce que tu veux.
    "Le bon ni le mauvais ne me feraient de peine si si si je savais que j'en aurais l'étrenne." B.V.
    Non au langage SMS ! Je ne répondrai pas aux questions techniques par MP.
    Eclipse : News, FAQ, Cours, Livres, Blogs.Et moi.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 32
    Points : 22
    Points
    22
    Par défaut
    Merci Xavlours pour ta réponse


    Pour bloquer l'évenement ( et donc éviter le décalage non voulu), j'ai ajouté un Event.consume(); comme cela:

    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
     
    addKeyListener(new KeyAdapter() {
       public void keyPressed( KeyEvent e) 
        { 			
           if ( ((e.getKeyCode() == KeyEvent.VK_ENTER) ||(e.getKeyCode() == KeyEvent.VK_TAB)	 ) 
      	&&((getSelectRow()+1) == getDataTableau().getHauteur() ) 
       	&&(getSelectColumn()== getDataTableau().getLargeur()	 ) )  
    // si touche TAB ou ENTER a la fin du tableau
       				{
       					addNewRow();
        					e.consume();
       					// puis placer ma selection ou je veux a la main... 
      					changeSelection( ........ );
       					}	
      			}	
       		});
    voila apparement cela fonctionne, mais je suis pas vraiment sur de moi.
    Ce genre de bidouillage peut'il entrainer des problemes non voulus ( au niveau de la selection par ex.?)

    Sinon j'essayerais ta méthode, mais la mécanique de mise en place est qd mm plus lourde.

  4. #4
    Membre émérite
    Avatar de xavlours
    Inscrit en
    Février 2004
    Messages
    1 832
    Détails du profil
    Informations forums :
    Inscription : Février 2004
    Messages : 1 832
    Points : 2 410
    Points
    2 410
    Par défaut
    Ah, oui, j'avais oublié qu'il faut consommer l'Event, et j'ai corrigé mon code plus haut (WHEN_FOCUSED -> WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).

    Je vois 2 différences entre le KeyListener et les KeyBindings :
    - en remplaçant le KeyBinding juste dans l'ActionMap (sans créer de clé), tous les KeyBindings associés à cette action sont changés. Par exemple si "Ctrl + B" fait la même chose que "Enter", tu peux changer les 2 comportements d'un coup ;
    - lors de l'édition, ce n'est pas la JTable qui a le focus, et le KeyListener ne fonctionnera pas. Alors qu'avec un KeyBinding si (avec l'option WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).
    "Le bon ni le mauvais ne me feraient de peine si si si je savais que j'en aurais l'étrenne." B.V.
    Non au langage SMS ! Je ne répondrai pas aux questions techniques par MP.
    Eclipse : News, FAQ, Cours, Livres, Blogs.Et moi.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 32
    Points : 22
    Points
    22
    Par défaut
    J'ai un autre soucis maintenant (sans rapport) portant sur l'édition de mes composants graphiques à partir du CellEditor (j'imagine...).

    Mon problème est que lorsque je cherche à éditer ma ligne ( composée d'un JTextField, JCheckBox, et 4 autres compos graphiques de ma librairie graphique), l'édition des 2 premiers items fonctionne bien, mais la sélection des suivants ne permet pas l'édition des infos ( le "mode édition" ne se déclanche pas).

    Pourtant la saisie est parfois possible, lorsque je sélectionne plusieurs cellules par exemple, et que je clique sur une des cellule n'ayant pas la "sélection principale" (le cadre en gras). Le composant est donc bien présent.


    Voila si quelqu'un voit une piste, n'hésitez pas

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 32
    Points : 22
    Points
    22
    Par défaut
    Si ca peut aider,

    la commande
    table.clearSelection();

    placée dans la méthode
    public Component getTableCellEditorComponent(JTable table, Object value,
    boolean isSelected,
    int row, int column)

    me permet d'arriver au mode "édition" de mes cellules spéciales, mais n'est pas acceptable car elle ne permet pas de saisir directement l'info ( le carret n'est pas présent, sauf apres un clic souris supplémentaire dans la cellule, nécessaire pour replacer la sélection) ...


    probleme de sélection donc je pense
    Me faut-il passer par ListSelectionListener ou autre?

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 32
    Points : 22
    Points
    22
    Par défaut
    Je me permet de Upper le sujet.

    J'aurais besoin de savoir comment se passe précisément l'attribution par défaut des SelectionListeners sur les objets JComponents... et l'utilisation des PropertyChangeListener pour les JComponents.
    Je crois que mon probleme vient de là, à savoir que les listeners sont mal (ou pas) redéfinis pour mes objets n'appartenant pas à JComponent.

    Peu d'info là dessus sur le web, qq'un a-t'il deja instancié ses propres composants graphiques (dérivés de JSuite -> JPVEdit) ds une JTable?

  8. #8
    Membre émérite
    Avatar de xavlours
    Inscrit en
    Février 2004
    Messages
    1 832
    Détails du profil
    Informations forums :
    Inscription : Février 2004
    Messages : 1 832
    Points : 2 410
    Points
    2 410
    Par défaut
    Si je comprends bien, les Editors qui utilisent des composants Swing fonctionnent bien, alors que ceux utilisant une librairie externe ne s'activent pas tout le temps. C'est ça ?

    Bon à priori, la librairie externe utilise des descendants de JComponent, sinon ça va être vraiment difficile d'intégrer ça dans une JTable. Ces composants implémentent-ils l'interface TableCellEditor tout seuls, ou alors tu as écrit des classes qui font le lien ? Dans ce cas, un peu de code nous aiderait bien.

    Sinon, les SelectionListener sont en général gérés par le LookAndFeel, mais les SelectionEvents sont lancés depuis un MouseListener (lui aussi géré par le LookAndFeel). Idem pour les PropertyListeners, mais je ne vois pas trop ce qu'ils viennent faire ici.
    "Le bon ni le mauvais ne me feraient de peine si si si je savais que j'en aurais l'étrenne." B.V.
    Non au langage SMS ! Je ne répondrai pas aux questions techniques par MP.
    Eclipse : News, FAQ, Cours, Livres, Blogs.Et moi.

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 32
    Points : 22
    Points
    22
    Par défaut
    Bonjour Xavlours

    les SelectionListener sont en général gérés par le LookAndFeel, mais les SelectionEvents sont lancés depuis un MouseListener (lui aussi géré par le LookAndFeel). Idem pour les PropertyListeners, mais je ne vois pas trop ce qu'ils viennent faire ici.
    En effet, je crois que j'ai cherché un peu loin là, ça ne doit pas etre lié a mon probleme.


    Pour en revenir au sujet, j'ai donc un JTable qui doit pouvoir afficher (OK) et éditer (pas OK) :
    - des JTextField et JCheckBox, là pas de soucis,
    - des objets graphiques descendants de JComponent en effet, qui ne passent pas seuls en mode édition. Impossible avec la souris, ils sont éditables uniquement avec l'appuis d'une touche du clavier, mais leur contenu est entierement sélectionné (pas comme JTextField ou le curseur se place a la fin)




    voici le code de mon CellEditor :

    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
    135
    136
    137
    138
     
    public class DataTableauCellEditor 	extends AbstractCellEditor
    					implements TableCellEditor, Serializable
    {
    	/**
             * serialVersionUID
             */
    	private static final long serialVersionUID = -4042935954426383895L;
     
    	protected JCheckBox		box;
    	protected MonObjetDate		date;
    	protected MonObjetNombre 	entier;
    	protected MonObjetMontantCent 	montant;
    	protected JTextField 		text;
     
    	protected Infos		inf = null;
     
    	Object objetCourant;
     
    	/**
             * 
             */
    	public DataTableauCellEditor( ) {	
    	}
     
     
    	public Component getTableCellEditorComponent(JTable table, Object value,
    		  boolean isSelected,
    		  int row, int column)	  
    	{
    		Component retour = null;
     
    		// apporte un mieux, les Composants devenant éditable avec touche clavier pressée
    		table.setSurrendersFocusOnKeystroke(true);
     
     
    		if (!isSelected) {
    			 retour = null;
    		 } else {
     
    			  // On récupère le type de composant contenu dans la cellule
    			  // pour lui affecter son Editor
     
    			  inf = (Infos) value;
     
    			  switch (inf.getType()) 
    			  {
    			 	case Infos.TYPE_BOOLEEN :
    			 	{
    					 box = new JCheckBox();
    					 if( inf.getAlignment()!=null )	{
    						 box.setHorizontalAlignment(inf.getAlignment().intValue()); 
    					 }
    					 if( inf.getValeur() == Boolean.TRUE )	 { box.setSelected(true);
    					 } else { box.setSelected(false); 
    					 }
    					 box.setHorizontalAlignment(SwingConstants.CENTER);
    					 box.setEnabled(true);
    					 box.setBorder(null);
    					 objetCourant = box;
    					 retour = box;
    					 break;
    			 	}
    			 	case Infos.TYPE_STRING :	
    			 	{
    					 Infos cel = new Infos();
    					 text = new JTextField();
    					 if (value != null) { cel = (Infos) value;
    					 } else { cel.setValeur(""); 
    					 }
    					 text.setBorder(BorderFactory.createEmptyBorder());
    					 text.setText(cel.getValeur().toString());
    					 text.getCaret().setVisible(true);
    					 text.setEnabled(true);
    					 text.setEditable(true);
    					 objetCourant = text;
    					 retour = text;
    					 break;
    			 	}
    			 	case InfosCellule.TYPE_DATE : 	
    			 	{
    					 date = new MonObjetDate();
    					 date.setBorder(null);
    					 date.setEnabled(true);
    					 date.setEditable(true);
    					 objetCourant = date;
    					 retour = date;
    					 break;
    			 	}
    			 	case InfosCellule.TYPE_ENTIER : 
    			 	{
    			 		 entier = new MonObjetNombre();
    					 entier.setBorder(null);
    					 entier.setEnabled(true);
    					 entier.setEditable(true);
    					 entier.setCaretHidden(false);
    			 		 entier.setTextNonFormate(inf.getValeur().toString());
    					 objetCourant = entier; 
    					 retour = entier;
    					 break;
    			 	}
    case InfosCellule.TYPE_MONTANT :	 
    			 	{
    					 montant = new MonObjetMontant();
    					 montant.setBorder(null);
    					 montant.setEnabled(true);
    					 montant.setEditable(true);
    					 montant.setTextNonFormate(inf.getValeur().toString());
    					 objetCourant = montant;
    					 retour = montant;
    					 break;
    			 	}
    			 	default:  {retour = new JLabel(""); }
    			  }
    		 }
    		return retour;
    	 }
     
     
    	public Object getCellEditorValue(){
     
    		if 		(objetCourant.equals(box)) 			{		
    			return new Boolean(box.isSelected());
    		} else if (objetCourant.equals(text)) 		{
    			return text.getText();
    		} else if (objetCourant.equals(entier) ) 	{
    			return entier.getTextNonFormate();
    		} else if (objetCourant.equals(montant)) 	{
    			return montant.getTextNonFormate();
    		} else if (objetCourant.equals(date) ) 		{
    			return date.getText();
     		} else {
     			return new JLabel ("PAR DEFAUT");
     		}	
    	}
     
     
    // ... plus tous les listeners nécessaires de la forme super.le_listener();

    mon tableau est rempli d'objets Infos, contenants un nom, un type d'objet et l'objet en question.



    Le but:
    - obtenir l'édition sur simple clic souris sur la cellule
    - obtenir l'édition lorsque la cellule devient sélectionnée, par ex apres TAB ou ENTER ( ne pas avoir a rappuyer sur une touche)

    Merci

  10. #10
    Membre émérite
    Avatar de xavlours
    Inscrit en
    Février 2004
    Messages
    1 832
    Détails du profil
    Informations forums :
    Inscription : Février 2004
    Messages : 1 832
    Points : 2 410
    Points
    2 410
    Par défaut
    Ah, je comprends mieux. Je pense en effet qu'un SelectionListener qui appelle setEditingRow/Column doit suffire. Pense à mettre le ListSelectionModel en SINGLE_SELECTION, sinon c'est un peu absurde.
    Si ça ne suffit pas, essaie dans l'ordre :
    - appeler setEditingRow/Column dans un SwingUtilities.invokeLater
    - appeler isEditing, et besoin appeler getCellEditor().stopEditing() avant setEditingRow/Column

    Je n'ai pas encore testé, mais si ça ne suffit pas, dis le moi et je mettrai les mains dedans.
    "Le bon ni le mauvais ne me feraient de peine si si si je savais que j'en aurais l'étrenne." B.V.
    Non au langage SMS ! Je ne répondrai pas aux questions techniques par MP.
    Eclipse : News, FAQ, Cours, Livres, Blogs.Et moi.

  11. #11
    Membre expérimenté Avatar de herve91
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    1 282
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 282
    Points : 1 608
    Points
    1 608
    Par défaut
    Bonsoir,
    essaie en enlevant les lignes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if (!isSelected) {
       retour = null;
    } else {
    En effet, l'éditeur est installé AVANT que le modèle de sélection soit mis à jour. En résumé, la cellule qui passe en édition n'est pas sélectionnée.

Discussions similaires

  1. [JTable] Problème Listener lors de la sélection d'une cellule
    Par superstarz dans le forum Composants
    Réponses: 1
    Dernier message: 07/01/2013, 16h05
  2. Problème Sélection Cellules JTable
    Par darling dans le forum Composants
    Réponses: 1
    Dernier message: 10/04/2010, 12h20
  3. [JTable] problème après suppression d'une ligne
    Par fredo3500 dans le forum Composants
    Réponses: 7
    Dernier message: 17/03/2005, 10h01
  4. [JTable] Problème d'affichage des données
    Par ddams dans le forum Composants
    Réponses: 2
    Dernier message: 15/09/2004, 17h07
  5. [JTable] Empêcher sélection de certaines cellules
    Par Oliveuh dans le forum Composants
    Réponses: 6
    Dernier message: 28/07/2004, 12h47

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