Je suis tombé sur un problème avec Combobox dans javafx2.2. Voici le scénario:
Cette sous-fenêtre contient 6 zones de liste déroulante . Trois d'entre elles ont des éléments fixes: cboReport, cboSales, cboSend. Trois d'entre eux tirent leurs données d'une base de données (ObservableList) et les remplissent lorsque le volet devient visible: cboFile, cboCustomer, cboVet
Lorsque la fenêtre se ferme, les données du volet sont réinitialisées via une méthode resetGUI_editFilePane (). Il y a des lignes comme:
...
cboReport.getSelectionModel().clearSelection();
cboSales.getSelectionModel().clearSelection();
cboSend.getSelectionModel().clearSelection();
cboFile.getSelectionModel().clearSelection();
cboCustomer.getSelectionModel().clearSelection();
cboVet.getSelectionModel().clearSelection();
cboFile.getItems().clear();
cboCustomer.getItems().clear();
cboVet.getItems.clear();
...
Lorsque l'utilisateur ouvre à nouveau le volet en appuyant sur le bouton 'editFile', je remarque que seules les listes déroulantes 'élément fixe' ont effacé leur sélection. Les listes déroulantes remplies de manière dynamique affichent le dernier élément sélectionné bien que la valeur de la sélection elle-même soit null
. Cela ressemble à un bug graphique pour moi ou est-ce que je fais quelque chose de mal?
Existe-t-il un moyen de contourner ce problème ou quelle est la meilleure méthode pour réinitialiser une liste déroulante?
EDIT 2014/08/27:
Ce n'est officiellement pas un bug (clearSelection () n'efface pas la valeur):
https://bugs.openjdk.Java.net/browse/JDK-8097244
La "solution de contournement" officielle consiste à effacer la valeur de la ComboBox après avoir effacé la sélection.
cb.getSelectionModel().clearSelection();
// Clear value of ComboBox because clearSelection() does not do it
cb.setValue(null);
J'ai rencontré à peu près exactement la même situation et je suis tombé sur votre question en cherchant une solution. Heureusement, j'ai trouvé une solution qui oblige les ComboBox à se réinitialiser. Lorsque vous réinitialisez les données sur votre volet, au lieu de faire quelque chose comme:
cboVet.getSelectionModel().clearSelection();
cboVet.getItems.clear();
faire quelque chose comme ça ...
parentNode.getChildren().remove(cboVet);
cboVet = new ComboBox(); // do whatever else you need to format your ComboBox
parentNode.add(cboVet);
Vous aurez également besoin de refaire setItems () sur votre ComboBox pour que le nouveau soit rempli. Ce n'est pas une solution idéale, mais elle semble fonctionner comme je l'espère, la méthode clearSelection () fournie.
C'est très simple. Il vous suffit de travailler avec la propriété value de ComboBox. Voici ....
ComboBox c;
c.valueProperty().set(null);
J'espère que cela fonctionne pour vous :-D
Vous pouvez récupérer les éléments et les supprimer tous:
cboVet.getItems().removeAll(cboVet.getItems());
Je viens de tester une solution de travail avec le JDK Java 1.7.11:
combobox.setSelectedItem(null);
combobox.setValue(null);
J'espère que ça aide :)
J'utilise la réflexion avec manipulation directe du champ buttonCell dans un skin ComboBox:
@SuppressWarnings({ "rawtypes", "unchecked" })
public static <T> void resetComboBox(ComboBox<T> combo) {
Skin<?> skin = combo.getSkin();
if(skin==null){
return;
}
combo.setValue(null);
Field buttonCellField;
try {
buttonCellField = skin.getClass().getDeclaredField("buttonCell");
buttonCellField.setAccessible(true);
ListCell buttonCell = (ListCell) buttonCellField.get(skin);
if(buttonCell!=null){
StringProperty text = buttonCell.textProperty();
text.set("");
buttonCell.setItem(null);
}
} catch (NoSuchFieldException
| SecurityException
| IllegalArgumentException
| IllegalAccessException e) {
e.printStackTrace();
}
}
Je pense que c'est également possible en fournissant votre propre implémentation de buttonCell via la propriété buttonCellFactory
Je dois effacer la sélection de la liste déroulante. Et ce code a fonctionné pour moi:
List<Object> list = new ArrayList<>(comboBox.getItems());
comboBox.getItems().removeAll(list);
comboBox.getItems().addAll(list);
Pour effacer SelectionModel, je n'ai rien trouvé de mieux que de créer une nouvelle instance de Combobox (les réponses précédentes sont mises à jour):
myParentNode.getChildren().remove(myCombobox);
myCombobox = new ComboBox();
myParentNode.add(myCombobox);
Mais cette solution engendre d'autres problèmes: si vous utilisez fxml, cette liste déroulante sera placée au mauvais endroit et avec de mauvais paramètres. Certains paramètres fxml sont difficilement reproduits directement à partir du code de classe de votre contrôleur et il est affreux de le faire chaque fois que vous devez effacer la liste déroulante.
La solution utilise des composants personnalisés au lieu de créer des instances directement dans le code de la classe du contrôleur principal, même si ces composants sont standard. Cela permet également de libérer certaines lignes de votre classe de contrôleur principal en déplaçant les méthodes d'événement associées aux composants et d'autres méthodes dans un fichier de classe séparé, dans lequel vous utilisez une référence à votre classe de contrôleur principal.
Pour créer des composants personnalisés dans JavaFX FXML Application, voir http://docs.Oracle.com/javafx/2/fxml_get_started/custom_control.htm , mais notez que la classe CustomControlExample n'est pas nécessaire pour chaque composant personnalisé. votre application, si elle a déjà une classe de point d’entrée avec la méthode start (étape Satge).
Comment résoudre les erreurs possibles en faisant référence à une classe de contrôleur de composant personnalisé à une classe de contrôleur principale, disponible dans JavaFx: comment référencer l'instance principale de la classe Controller à partir de la classe CustomComponentController?
J'ai eu le même problème avec une ComboBox. Le bouton Cellule de la ComboBox n'est pas mis à jour correctement lorsque je change les éléments de la ComboBox. Cela ressemble à un bug graphique.
J'utilise la manipulation directe du champ ButtonCell dans ComboBox.
combo.getButtonCell().setText("");
combo.getButtonCell().setItem(null);
C'est la meilleure solution que j'ai trouvée sans recréer le ComboBox.