Tri alphabétique dans une JComboBox [Résolu]

Messages postés
37
Date d'inscription
vendredi 23 mars 2018
Dernière intervention
20 septembre 2018
- 23 mars 2018 à 09:57 - Dernière réponse :
Messages postés
37
Date d'inscription
vendredi 23 mars 2018
Dernière intervention
20 septembre 2018
- 29 mars 2018 à 13:24
Bonjour,

Je charge dans une combo le nom de sous-dossiers d'un dossier avec le code ci-dessous.
Je tente de classer par ordre alphabétique les noms avec un tableau de string et "Arrays.sort". Mais cela ne fonctionne pas. Pour info, dans la JComboBox, ce qui est affiché est Nom Prénom date de naissance (ex : JAVA jadore 22.03.2018)
Merci de votre aide.

public List<String> findFoldersInDirectory(String directoryPath) {
File directory = new File(directoryPath);

FileFilter directoryFileFilter = new FileFilter() {
public boolean accept(File file) {
return file.isDirectory();
}
};

File[] directoryListAsFile = directory.listFiles(directoryFileFilter);

List<String> foldersInDirectory = new ArrayList<String>(directoryListAsFile.length); // liste des dossiers


for (File directoryAsFile : directoryListAsFile) {

foldersInDirectory.add(directoryAsFile.getName()); //on ajoute les noms des dossiers

String[] arrays=new String[] {directoryAsFile.getName()};
Arrays.sort(arrays);

for (int i = 0; i < arrays.length; i++) {

this.addItem(arrays[i]);
}
Afficher la suite 

Votre réponse

1 réponse

Messages postés
15830
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
21 novembre 2018
23 mars 2018 à 17:50
0
Merci
Bonjour,

String[] arrays=new String[] {directoryAsFile.getName()};
Arrays.sort(arrays); 

Ton tableau ne contient qu'un seul élément, ici ça ne sert à rien de trier quoi que ce soit...

Si tu veux un tri pertinent il faudrait le faire sur l'ensemble des éléments ajoutés.
Par exemple un
Collections.sort(foldersInDirectory);
à faire à la fin.
Messages postés
37
Date d'inscription
vendredi 23 mars 2018
Dernière intervention
20 septembre 2018
- 28 mars 2018 à 22:13
Voici la class permettant l'autocompletion dans laquelle j'ai inséré une méthode permettant de lister les dossiers dans la combo. Je remercie d'ailleurs les personnes permettant de mettre en ligne ces codes.

import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.FileFilter;
import java.util.*;
import java.util.List;

import javax.swing.*;
import javax.swing.text.*;

import com.sun.tools.javac.code.Attribute.Array;

public class AutoComplete extends JComboBox implements JComboBox.KeySelectionManager
{
private String searchFor;
private long lap;
public class CBDocument extends PlainDocument
{
public void insertString(int offset, String str, AttributeSet a) throws BadLocationException
{
if (str==null) return;
super.insertString(offset, str, a);
if(!isPopupVisible() && str.length() != 0) fireActionEvent();
}
}
public AutoComplete(Object[] items)
{

super(items);

this.setToolTipText("Sélectionner un dossier");
this.setForeground(Color.BLACK);
this.setOpaque(true);
this.setMaximumRowCount (10 ); //nombre max d'élément afficher
this.setPreferredSize(new Dimension(600,30));
this.setFocusable(true);
this.setEditable(true);



//this.setFont( Font.decode("Serif"));

//initComboSelectionner();

findFoldersInDirectory("/Users/moi/eclipse-workspace/Doc JAVA/DOSSIERS");


lap = new java.util.Date().getTime();
setKeySelectionManager(this);
JTextField tf;
if(getEditor() != null)
{
tf = (JTextField)getEditor().getEditorComponent();
if(tf != null)
{
tf.setDocument(new CBDocument());
addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
JTextField tf = (JTextField)getEditor().getEditorComponent();
String text = tf.getText();
ComboBoxModel aModel = getModel();
String current;
for(int i = 0; i < aModel.getSize(); i++)
{
current = aModel.getElementAt(i).toString();
if(current.toLowerCase().startsWith(text.toLowerCase()))
{
tf.setText(current);
tf.setSelectionStart(text.length());
tf.setSelectionEnd(current.length());
break;
}
}
}
});
}
}
}
public int selectionForKey(char aKey, ComboBoxModel aModel)
{
long now = new java.util.Date().getTime();
if (searchFor!=null && aKey==KeyEvent.VK_BACK_SPACE && searchFor.length()>0)
{
searchFor = searchFor.substring(0, searchFor.length() -1);
}
else
{
// System.out.println(lap);
// Kam nie hier vorbei.
if(lap + 1000 < now)
searchFor = "" + aKey;
else
searchFor = searchFor + aKey;
}
lap = now;
String current;
for(int i = 0; i < aModel.getSize(); i++)
{
current = aModel.getElementAt(i).toString().toLowerCase();
if (current.toLowerCase().startsWith(searchFor.toLowerCase())) return i;
}
return -1;
}
public void fireActionEvent()
{
super.fireActionEvent();
}


//methode qui permet de charger les dossiers dans la combobox
public List<String> findFoldersInDirectory(String directoryPath) {

File directory = new File(directoryPath); // chemin d'acces aux dossiers

FileFilter directoryFileFilter = new FileFilter() {
public boolean accept(File file) {
return file.isDirectory();
}
};

File[] directoryListAsFile = directory.listFiles(directoryFileFilter);

List<String> foldersInDirectory = new ArrayList<String>(directoryListAsFile.length); // liste des dossiers


Collections.sort(foldersInDirectory);
for (File folderInDirectory: foldersInDirectory)
this.addItem(folderInDirectory);

/*
for (File directoryAsFile : directoryListAsFile) {

//foldersInDirectory.add(directoryAsFile.getName()); //on ajoute les dossiers au fur et à mesure à la liste
// combo1.addItem(directoryAsFile.getName()); //ajout à la combobox
combo1.addItem(foldersInDirectory); //ajout à la combobox
// //this.addItem(foldersInDirectory);

}
  • / return foldersInDirectory; } }
Messages postés
15830
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
21 novembre 2018
>
Messages postés
37
Date d'inscription
vendredi 23 mars 2018
Dernière intervention
20 septembre 2018
- 28 mars 2018 à 23:06
Ok, je croyais que c'était
this.addItem(folderInDirectory);
le problème et je ne comprenais pas.
Mais en fait c'est le
for (File folderInDirectory : foldersInDirectory)
qui coince (et en relisant tes messages tu l'avais bien dit...)

Explication : foldersInDirectory est une List<String> donc Java attends à ce que folderInDirectory soit un String aussi.

Attention : dans ton code foldersInDirectory est une liste vide !
En effet, tu l'as créé à la bonne taille mais tu ne l'as jamais rempli.

File[] directoryListAsFile = directory.listFiles(directoryFileFilter);

List<String> foldersInDirectory = new ArrayList<String>(directoryListAsFile.length);

Collections.sort(foldersInDirectory);
for (File folderInDirectory : foldersInDirectory)
    this.addItem(folderInDirectory);

Donc ici, tu va trier une liste vide, ce qui ne fera pas ce que tu veux.

Remarque : dans un modèle MVC il vaut mieux séparer la recherche et le tri des fichiers d'une part et l'ajout au combobox d'autre part.
Ici ta méthode devrait donc renvoyer en résultat l'ensemble des noms de fichiers triés (sans effet de bord sur la ComboBox). Et c'est en appelant cette méthode que tu ajoutes les items.

Voici une version "corrigée" de la méthode entière (à vérifier).

public SortedSet<String> findFoldersInDirectory(String directoryPath) {
    SortedSet<String> sortedFoldersNameInDirectory = new TreeSet<String>();
    for (File fileInDirectory : new File(directoryPath).listFiles())
        if (fileInDirectory.isDirectory())
            sortedFoldersNameInDirectory.add(fileInDirectory.getName());
    return sortedFoldersNameInDirectory;
}

// et l'appel :
SortedSet<String> sortedFoldersNameInDirectory = findFoldersInDirectory("/Users/moi/eclipse-workspace/Doc JAVA/DOSSIERS");
for (String folderNameInDirectory : sortedFoldersNameInDirectory)
    this.addItem(folderNameInDirectory);

Remarque : depuis Java 8 on pourrait aussi coder comme ceci :

public SortedSet<String> findFoldersInDirectory(String directoryPath) {
    return Arrays.stream(new File(directoryPath).listFiles())
        .filter(File::isDirectory).map(File::getName)
        .collect(Collectors.toCollection(TreeSet::new));
}

// et l'appel :
findFoldersInDirectory("/Users/moi/eclipse-workspace/Doc JAVA/DOSSIERS")
    .forEach(this::addItem);

Remarque : j'ai utilisé un TreeSet plutôt qu'un Collection.sort() parce que c'est plus efficace de garder un ensemble trié au fur et à mesure des ajouts que de trier une liste complète d'un coup.
Messages postés
37
Date d'inscription
vendredi 23 mars 2018
Dernière intervention
20 septembre 2018
- 29 mars 2018 à 10:04
Merci pour ta version corrigée, elle marche nickel !
Effectivement, en re-analysant mon code, la liste était vide et java attendant un string. Par contre, une question : j'ai pu lire :

Les Set sont particulièrement adaptés pour manipuler une grande quantité de données. Cependant, les performances de ceux-ci peuvent être amoindries en insertion. Généralement, on opte pour un HashSet, car il est plus performant en temps d'accès, mais si vous avez besoin que votre collection soit constamment triée, optez pour un TreeSet.

Dans mon cas, avec plusieurs centaines de dossiers, ne faudrait-il pas une hashset ?
Messages postés
15830
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
21 novembre 2018
>
Messages postés
37
Date d'inscription
vendredi 23 mars 2018
Dernière intervention
20 septembre 2018
- 29 mars 2018 à 10:58
"si vous avez besoin que votre collection soit constamment triée, optez pour un TreeSet."
C'est ce que j'expliquais dans ma dernière remarque.
Ta question concerne le tri, si tu utilises un HashSet ce ne sera pas trié, d'où le TreeSet.

PS. Quand on parle de "grande quantité de données" ce n'est pas une centaine de valeurs (comme le nombre de sous-dossiers dans un dossier) c'est beaucoup plus.
Et si tu avais effectivement une "grande quantité de données" il serait inefficace de toutes les mettre dans une JComboBox.
Messages postés
37
Date d'inscription
vendredi 23 mars 2018
Dernière intervention
20 septembre 2018
- 29 mars 2018 à 13:24
parfait. Merci pour ces explications et surtout ton aide. Cela permet en plus de mieux comprendre le code. Un grand merci
Commenter la réponse de KX

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.