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

SWT/JFace Java Discussion :

[SWT] CCombo dynamique pour la saisie aisée des données


Sujet :

SWT/JFace Java

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 11
    Par défaut [SWT] CCombo dynamique pour la saisie aisée des données
    Bonjour,

    Dans une application java/swt, j'ai des CCombo et je voudrais rendre la saisie des données moins fastidieuse pour l'utilisateur en déroulant la Ccombo et en positionnant au fur et à mesure la surbrillance sur l'item le plus proche du text qu'il saisit, lui permettant de valider la proposition avec la touche entrée et sélectionner l'item.

    J'ai utilisé un Keylistener dans lequel je déroule la liste et recherche l'item approprié. Celà se passe bien, sauf que le text de la CCombo est remplacé immédiatement par l'item sélectionné, et que le curseur n'y reste pas pour permettre de continuer la saisie. Il ne me semble pas très efficace d'utiliser un seul caractère pour la recherche de l'item correspondant.

    Je ne sais pas si j'arrive à me faire comprendre, mais voici le code de mon keylistener :

    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
     
    natureCcmb.addKeyListener(new KeyAdapter(){
    			int index = -1;
    			public void keyReleased(KeyEvent e) {	
    				String text = natureCcmb.getText();
        			String[] items = natureCcmb.getItems();
    				if(e.character == SWT.CR) {
    					if(index >= 0) natureCcmb.setText(natureCcmb.getItem(index));
    					else natureCcmb.setText("");
    					natureCcmb.setListVisible(false);
    	    		}else{
    	    			natureCcmb.setListVisible(true);	    			
    	    			int i = 0;
    	    			boolean found = false;
    	    			while((!found)&&(i < items.length)){
    	    				found = items[i].toLowerCase().startsWith(text.toLowerCase());
    	    				if(found) index = i;
    	    				i++;
    	    			}	
    	    			if(index >= 0) natureCcmb.select(index);
    	    			natureCcmb.setText(text);
    	    			//natureCcmb.setFocus();
    	    		}	    					
    			}	
    		});
    Quelqu'un saurait-il quoi faire ?
    Merci d'avance

  2. #2
    Membre chevronné
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2007
    Messages
    340
    Détails du profil
    Informations personnelles :
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2007
    Messages : 340
    Par défaut
    Je vois bien ce que tu essayes de faire. Pour ce qui est de l'efficacité tu travailles sur un nombre de données assez faible dans une combo box (c'est rare d'avoir plusieurs milliers d'éléments sélectionnables par l'utilisateur) donc normalement il ne devrait pas y avoir de problème de ralentissement.
    Pour ce qui est de redonner le focus au champ de texte essaye la méthode setFocus() (ou forceFocus()) sur le CCombo, si elles ne marchent pas ça va être galère... il va falloir récupérer le champs de texte en identifiant de quel widget il s'agit via la méthode getChildren() et lui appliquer direcement la méthode setFocus().
    Pour placer le curseur au bon endroit tu dois utiliser la méthode setSelection(Point) de la classe CCombo.
    Je serais prèsque tenter de te conseiller de réécrire un widget qui fait ce que tu veux... au risque de me faire huer par les fervant défenseurs du "toujours réutiliser ce qui existe" (en l'occurence là ça n'existe pas vraiment).

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 11
    Par défaut CCombo dynamique pour la saisie aisé des données
    Bonjour,

    Merci soft0613 pour l'intérêt porté à ma requête. La méthode setFocus ne résout pas mon problème, l'item sélectionné précedemment est désélectionné (il reste quand même encadré, mais en pointillés plutôt qu'en surbrillance).

    La méthode forceFocus quand à elle ferme carrément la liste des items qui était déroulée.

    J'ai aussi essayé la méthode getChildren afin de récupérer le champ texte et lui appliquer directement le setFocus, mais je pense qu'elle ne retourne rien comme children, car toute tentative du genre getChildren()[0] me génère une exception ArrayIndexOutofBounds.

    Pour replacer le curseur, l'instruction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    natureCcmb.setSelection(new Point(0, text.length()));
    se contente de mettre en surbrillance le contenu du champ texte, pas de curseur pour continuer la saisie.

    J'ai pourtant assez souvent vu ça dans des programmes (surtout sur le web : google, youtube,...) je pensais que ce serait facile. SWT serait-il insuffisant ? L'idée de reécrire un widget me fait un peu peur, je ne suis pas une experte java, loin de là. Je ne sais comment faire.

    Aidez-moi svp

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    187
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 187
    Par défaut
    Voilà un exemple de code qui peut te donner une piste :

    L'idée, c'est d'afficher une popup contenant une liste en dessous du texte saisi; et de sélectionner le texte correspondant.

    Il te reste à encapsuler ça proprement dans un composite qui traite correctement l'affichage, le dispose(), et les évènements (clic dans la liste, entrée, etc.), et le tour est joué. Remarque, c'est à peu près ce que fait la CCombo.

    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
    private static Shell parent;
    	private static Text natureCcmb;
     
    	private static Shell aide;
    	private static List suggestions;
     
    	private static String[] libelles = new String[] {
    		"abcde", "abcjfhd", "bcdef", "bcdsdqsd", "cdefg", "cdedsqd",
    	};
     
    	public static void test() {
    		final Display display = new Display ();
    		Shell shell = new Shell (display);
     
    		shell.setLayout(new FillLayout());
     
    		natureCcmb = new Text(shell, SWT.MULTI); //Text et non combo 
     
    		//Evènnements déclenchant l'affichage
    		natureCcmb.addKeyListener(new KeyAdapter() {
    			@Override
    			public void keyReleased(KeyEvent e) {
    				creerAide();
    				afficherAide();
    			}
    		});
    		//Evènnements déclenchant la fermeture
    		natureCcmb.addFocusListener(new FocusAdapter() {
    			@Override
    			public void focusLost(FocusEvent e) {
    				supprimerAide();
    			}
    		});
    		natureCcmb.addControlListener(new ControlAdapter() {
    			@Override
    			public void controlMoved(ControlEvent e) {
    				supprimerAide();
    			}
    		});
    		shell.addShellListener(new ShellAdapter() {
    			@Override
    			public void shellDeactivated(ShellEvent e) {
    				supprimerAide();
    			}
    		});
    		shell.addControlListener(new ControlAdapter() {
    			@Override
    			public void controlMoved(ControlEvent e) {
    				supprimerAide();
    			}
    			@Override
    			public void controlResized(ControlEvent e) {
    				supprimerAide();
    			}
    		});
     
    		shell.setSize(200, 100);
    		shell.open ();
     
    		while (!shell.isDisposed()) {
    			if (!display.readAndDispatch ()) display.sleep ();
    		}
    		display.dispose ();
    	}
     
    	private static void afficherAide() {
    		//Sélection en fonction de la saisie
    		String critere = natureCcmb.getText();
    		if (! critere.isEmpty()) {
    			for (int i=0; i<suggestions.getItemCount(); i++) {
    				if (suggestions.getItem(i).startsWith(critere)) {
    					suggestions.select(i);
    					return;
    				}
    			}
    		}
    		suggestions.setSelection(new int[]{});
    	}
     
    	private static void creerAide() {
    		if (aide != null) return;
    		//Création de la popup en dessous du texte
    		aide = new Shell(parent, SWT.NO_TRIM | SWT.ON_TOP);
    		aide.setLayout(new FillLayout());
     
    		Point loc = natureCcmb.toDisplay(0, 0);
    		Point taille = natureCcmb.getSize();
    		aide.setSize(taille.x, 200);
    		aide.setLocation(loc.x, loc.y + taille.y);
    		//Remplissage
    		suggestions = new List(aide, SWT.SINGLE);
    		for (String s : libelles) {
    			suggestions.add(s);
    		}
    		//Affichage
    		aide.setVisible(true);
    	}
     
    	private static void supprimerAide() {
    		if (aide == null) return;
    		aide.dispose();
    		aide = null;
    	}

  5. #5
    Membre chevronné
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2007
    Messages
    340
    Détails du profil
    Informations personnelles :
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2007
    Messages : 340
    Par défaut
    Si ça peut t'aider.
    Fichiers attachés Fichiers attachés

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 11
    Par défaut
    Bonjour,

    Merci bien, soft0613 et Washmid pour cette réactivité. Ces codes vont m'aider à écrire un controle qui fait ce que je veux, comme je l'ai finalement résolu.

    Je rencontre cependant un problème avec le code du CTextField de soft0613. (je rappelle que je ne suis qu'une débutante en java). J'essaye d'ajouter à mon objet CTextField un FocusListener qui se charge de définir sa liste d'items avec des valeurs récupérées dans une base de données. Cette fonction ne s'exécute pourtant pas, à l'exécution rien n'apparaît dans la console. Que devrais-je ajouter au code de CTextfield pour prendre en compte des évènements de type FocusAdapter ?

    Merci.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    natureCtfd = new CTextField (shell, SWT.BORDER);
    		natureCtfd.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
     
    		natureCtfd.addFocusListener(new FocusAdapter(){
    			public void focusGained(FocusEvent event){
    				getItemList("Nature", "");
    				System.out.print("liste des items de détail : ");
    				natureCtfd.setItems(itemlist);	
    			}
    		});

  7. #7
    Membre chevronné
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2007
    Messages
    340
    Détails du profil
    Informations personnelles :
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2007
    Messages : 340
    Par défaut
    C'est compliqué à expliquer et assez technique, si t'es intéressée je prend le temps, sinon prend juste la mise à jour.
    Fichiers attachés Fichiers attachés

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 11
    Par défaut
    Bonjour,

    Désolée pour ce délai de réponse. C'est un projet personnel sur lequel je ne travaille que pendant mon temps libre.

    Merci soft0613 pour cette modification, mon FocusListener s'exécute maintenant en chargeant la liste d'items.

    J'ai aussi effectué quelques modifications du code pour :
    afficher la liste des items au bon endroit -le positionnement du shell n'était pas bon
    prendre en charge les différences de casse dans onTextModify
    prendre en compte la saisie de la touche 'enter' dans onTextKeyDown

    C'est presque parfait, un dernier problème -enfin j'espère, lors de l'exécution, le shell du CTextField s'affiche automatiquement à l'ouverture de mon formulaire, et disparaît au Focus, les choses devraient être contraires. J'ai essayé d'y remédier en décommentant les instructions hideList(), même en insérant un shell.setVisible(false) à la fin de la fonction de création du shell, rien n'y fait, je ne sais plus trop quoi faire.

    Voici un exemplaire du nouveau code.
    Fichiers attachés Fichiers attachés

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    25
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 25
    Par défaut
    Bonjour,

    J'ai actuellement un souci du même ordre. On utilise une CCombo pour gérer des listes déroulantes. Le pb, c'est que lorsque l'on saisit une lettre, la première item qui commence par cette lettre est directement sélectionnée, on ne peut continuer la saisie. Ce qu'on souhaiterait, c'est que qd on saisit 'D', la liste se positionne sur 'DADA', puis 'E' => la liste se repositionne sur 'DEDE'. Un filtre autrement dit.
    Est-ce possible avec CCombo ?
    Voici le source de la classe qqui hérite de KTableCellEditor:
    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
     
    public class CelluleCombo extends KTableCellEditor {
    	private CCombo m_Combo;
    	private String m_Items[];
    	private Cursor m_ArrowCursor = new Cursor(Display.getDefault(), SWT.CURSOR_ARROW);
     
        private KeyAdapter keyListener = new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                try {
                    onKeyPressed(e);
                 } catch (Exception ex) {
                    // Do nothing
                }
                e.doit = false;
           }
        };
     
        private TraverseListener travListener = new TraverseListener() {
            public void keyTraversed(TraverseEvent e) {
                onTraverse(e);
            }
        };
     
    	public void open(KTable table, int row, int col, Rectangle rect) {
    		super.open(table, row, col, rect);
    		String content = m_Model.getContentAt(m_Col, m_Row).toString(); 
    		int oIndexEspace = content.indexOf(" ");
    		if (oIndexEspace != -1)
    		{
    			content = content.substring(0, oIndexEspace);
    		}
    		m_Combo.setText(content);
    		m_Combo.setSelection(new Point(0, content.length()));
    	}
     
    	public void close(boolean save)
    	{
    		String content = m_Combo.getText(); 
    		int oIndexEspace = content.indexOf(" ");
    		if (oIndexEspace != -1)
    		{
    			content = content.substring(0, oIndexEspace);
    		}
    		if (save)
                m_Model.setContentAt(m_Col, m_Row, content);
     
            m_Combo.removeKeyListener(keyListener);
            m_Combo.removeTraverseListener(travListener);
            super.close(save);
            m_Combo = null;
            m_ArrowCursor.dispose();
    	}
     
    	protected Control createControl() {
    		m_Combo = new CCombo(m_Table, SWT.NORMAL);
    		m_Combo.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
     
    		if (m_Items != null)
    			m_Combo.setItems(m_Items);
     
            m_Combo.addKeyListener(keyListener);        
            m_Combo.addTraverseListener(travListener);
     
    		m_Combo.setCursor(m_ArrowCursor);
    		return m_Combo;
    	}
     
    	protected void onTraverse(TraverseEvent e)
        {
            // set selection to the appropriate next element:
            switch (e.keyCode)
            {
                case SWT.ARROW_UP: // Go to previous item
                case SWT.ARROW_DOWN: // Go to next item
                {
                    break;
                }
                default: {
                    super.onTraverse(e);
                    break;
                }
            }
        } 
     
    	public void setBounds(Rectangle rect) 
    	{
    		super.setBounds(new Rectangle(rect.x, rect.y+1,
    									  rect.width, rect.height-2));
    	}
     
    	public void setItems(String items[]) {
    		m_Items = items;
    	}
     
        public void setContent(Object content) {
           if (content instanceof Integer) {
               m_Combo.select(((Integer)content).intValue());
           } else if (content instanceof String) {
               setSelectionToClosestMatch((String)content);
           } else {
               setSelectionToClosestMatch(content.toString());
           }
        }
     
        private void setSelectionToClosestMatch(String content) {
        	content = content.toLowerCase();
     
            String[] citems = m_Combo.getItems();
            String[] items = new String[citems.length];
            for (int i=0; i<citems.length; i++)
                items[i] = citems[i].toLowerCase();
     
            for (int length=content.length(); length>=0; length--) {
                String part = content.substring(0, length);
                for (int i=0; i<items.length; i++) 
                    if (items[i].startsWith(part)) {
                        m_Combo.select(i);
                        return;
                    }
            }
        }
    }
    C'est peut-etre pas très clair. On utilise Java 3.2.
    Merci par avance.

Discussions similaires

  1. besoin d'aider pour formulaire de modification des données
    Par lesultan2007 dans le forum ASP.NET
    Réponses: 2
    Dernier message: 29/08/2008, 18h41
  2. Problème pour changer le format des données
    Par Lize50 dans le forum SAS Base
    Réponses: 10
    Dernier message: 20/05/2008, 14h51
  3. [DOM] PHP et XML pour stocker et afficher des données
    Par sasaas dans le forum Bibliothèques et frameworks
    Réponses: 2
    Dernier message: 22/02/2008, 18h20
  4. Réponses: 1
    Dernier message: 10/06/2007, 07h22
  5. Aide pour diagramme de structure des données
    Par DeezerD dans le forum Décisions SGBD
    Réponses: 4
    Dernier message: 04/12/2004, 19h10

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