There is a class Street , with a description of an object of the type "street", which contains itself a private String name; , private int id; , private String tymeName and private int typeId , as well as public methods for getting the values ​​of these variables.

There is also a @FXML ComboBox<Street> streetList;

Task: you need to display a list of streets by taking names from the variable name using the getName method. and when selecting a specific street, start event handling via new ChangeListener<Street>() {...} .

Tried to do by analogy with TableView and TableColumn through .setCellFactory and collections.

Question: How to do it so that the name attribute is taken from the object to the list via getName and triggered a new ChangeListener<Street>() {...} passing the selected object for further work.

The spear method, in this case, does not help. How to realize the goal through the lines is clear. But what happens if, for example, Lenin and Lenin are on the list? And the first option is the avenue, the second is the street, but this should not be indicated in the drop-down list. Again, you can come up with a crawl through the strings, but, as it seems to me, it is possible to solve it by passing objects, and not just strings. In the tables, this method works.

  • link - an example of working with observable objects Note the class model and heteras - Peter Slusar
  • This example applies only to table classes, but not to the other controls. Initially I tried to solve the problem with this method. - The pogromist engineer

2 answers 2

Alternately answering questions.

you need to display a list of streets by taking names from the variable name using the getName method

 streetList.setCellFactory(p -> new ListCell <Street> () { @Override protected void updateItem(Street item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { setText(item.getName()); } else { setText(null); } } }); 

and when selecting a particular street, start event handling via new ChangeListener () {...}.

 streetList.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) - > { //тут описываешь логику лисенера }); 

I used lambda here, not new ChangeListener()...

But what happens if, for example, Lenin and Lenin are on the list? And the first option is the avenue, the second is the street, but in the drop-down list this should not be indicated

You will have both the avenue and the street if the Street objects are different (you must override the hashCode() and equals() methods

UPDATE

Regarding the picture in comments, there are 2 possible ways.

  1. Override the toString() method in the Street class

  2. Override buttonCell as follows

     streetList.setButtonCell(new ListCell < Street > () { @Override protected void updateItem(Street item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { setText(item.getName()); // или любую другую логику тут можно написать } else { setText(null); } } 
  • Thank you, half of the task is completed. There is only one thing left: the List is successfully displayed and the event takes the object, but when a list item is selected, the following is substituted in the text field:! Picture from ComboBox What else do you need to redefine so that the selected item is displayed correctly? - The pogromist engineer
  • one
    @ A pogromist engineer see answer update - Andrew Bystrov
  • Thanks, @AndrewBystrov! The question is completely settled. The sample class that used is added below. - The pogromist engineer

In addition to the answer @AndrewBystrov. In order to display one of its arguments in the ComboBox text box after selecting an item, you need to add a converter:

 public class StringConverterStreet extends StringConverter<Street> { @Override public String toString(Street street) { return street == null ? null : street.getName(); } @Override public Street fromString(String string) { return null; } } 

Used it before

 streetList.setConverter(new StringConverterStreet()); streetList.setCellFactory(p -> new ListCell <Street> () { @Override protected void updateItem(Street item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { setText(item.getName()); } else { setText(null); } } }); 

UPDATE

I took the advice of @AndrewBystrov and instead of the converter, I simply redefined the toString method. The result is the following:

 public class Street { private int id, typeId; private String typeName, name; public Street() { Street(null, null, null, null); } public Street(...) { ... } public String getName () { return name; } ... @Override public String toString () { return typeName + " " + name; } } 

Thanks a lot for your help!

  • one
    I'm certainly not sure, but it's not exactly that. If you look at the javadoc to the setConverter method, then the following is written: Converts the user-typed input (when the ComboBox is editable) Therefore, this is not exactly what is needed. Now I will add my answer to the picture from koment - Andrew Bystrov