Overview
JSelect<T> is a versatile dropdown select component with support for single and multiple selection, searchable options, custom item rendering, and automatic filtering. It extends StackPane and provides a modern, styled alternative to JavaFX’s standard ComboBox.
Generic Type
The type of items in the select list. Can be any object type.
Constructor
Creates a new JSelect with default configuration (single selection, not searchable). JSelect < String > select = new JSelect <>();
Methods
Item Management
Gets the observable list of items in the select. The observable list of all items
select . getItems (). addAll ( "Option 1" , "Option 2" , "Option 3" );
Selection (Single Mode)
Gets the selected item property for binding. The selected item property
select . selectedItemProperty (). addListener ((obs, old, newVal) -> {
System . out . println ( "Selected: " + newVal);
});
Gets the currently selected item (single selection mode). The currently selected item, or null if none selected
String selected = select . getSelectedItem ();
Sets the selected item (single selection mode). select . setSelectedItem ( "Option 2" );
Selection (Multiple Mode)
Gets the observable list of selected items (multiple selection mode). The list of selected items
ObservableList & lt;String & gt; selected = select . getSelectedItems ();
System . out . println ( "Selected count: " + selected . size ());
Configuration
Gets the multiple selection property for binding. The multiple selection property
Checks if multiple selection mode is enabled. True if multiple selection is enabled
setMultiple(boolean multiple)
Enables or disables multiple selection mode. True to enable multiple selection, false for single selection
select . setMultiple ( true );
Gets the searchable property for binding.
Checks if search functionality is enabled.
setSearchable(boolean searchable)
Enables or disables the search field in the dropdown. True to show search field, false to hide it
select . setSearchable ( true );
setPlaceholder(String placeholder)
Sets the placeholder text shown when no item is selected. The placeholder text (default: “Select an option”)
select . setPlaceholder ( "Choose a country..." );
setConverter(Function<T, String> converter)
Sets a function to convert items to display strings. A function that converts items to strings for display (default: Object::toString)
select . setConverter (user -> user . getFirstName () + " " + user . getLastName ());
setCellFactory(Callback<ListView<T>, ListCell<T>> factory)
Sets a custom cell factory for advanced item rendering (icons, custom layouts, etc.). factory
Callback<ListView<T>, ListCell<T>>
The cell factory callback
select . setCellFactory (param -> new CustomListCell ());
Style Classes
Applied to the root StackPane container
Applied to the clickable trigger area
Applied to the placeholder label
Applied to the selected value label
Applied to individual tags in multiple selection mode
Applied to the dropdown arrow icon
Applied to the popup dropdown container
Applied to the search field container
Applied to the ListView of items
Pseudo-classes
Applied to the select when the dropdown popup is visible
Usage Examples
Basic String Select
import com.jjarroyo.components.JSelect;
import javafx.scene.layout.VBox;
public class BasicSelectExample {
public VBox createCountrySelect () {
VBox container = new VBox ( 10 );
JSelect < String > countrySelect = new JSelect <>();
countrySelect . setPlaceholder ( "Select a country" );
countrySelect . getItems (). addAll (
"United States" ,
"Canada" ,
"Mexico" ,
"Brazil"
);
// Listen to selection changes
countrySelect . selectedItemProperty (). addListener ((obs, old, newVal) -> {
System . out . println ( "Selected country: " + newVal);
});
container . getChildren (). add (countrySelect);
return container;
}
}
Searchable Select
import com.jjarroyo.components.JSelect;
public class SearchableSelectExample {
public JSelect < String > createCitySelect () {
JSelect < String > citySelect = new JSelect <>();
citySelect . setPlaceholder ( "Search cities..." );
citySelect . setSearchable ( true );
// Add many items
citySelect . getItems (). addAll (
"New York" , "Los Angeles" , "Chicago" , "Houston" ,
"Phoenix" , "Philadelphia" , "San Antonio" , "San Diego" ,
"Dallas" , "San Jose" , "Austin" , "Jacksonville"
);
return citySelect;
}
}
Multiple Selection
import com.jjarroyo.components.JSelect;
import javafx.collections.ListChangeListener;
public class MultipleSelectExample {
public JSelect < String > createSkillsSelect () {
JSelect < String > skillsSelect = new JSelect <>();
skillsSelect . setPlaceholder ( "Select skills" );
skillsSelect . setMultiple ( true );
skillsSelect . setSearchable ( true );
skillsSelect . getItems (). addAll (
"Java" , "JavaScript" , "Python" , "C++" ,
"React" , "Angular" , "Vue.js" , "Node.js"
);
// Listen to selection changes
skillsSelect . getSelectedItems (). addListener (
( ListChangeListener . Change < ? extends String > c) -> {
System . out . println ( "Selected skills: " + skillsSelect . getSelectedItems ());
}
);
return skillsSelect;
}
}
Custom Object Select
import com.jjarroyo.components.JSelect;
public class User {
private int id ;
private String firstName ;
private String lastName ;
private String email ;
// Constructor, getters, setters...
public User ( int id , String firstName , String lastName , String email ) {
this . id = id;
this . firstName = firstName;
this . lastName = lastName;
this . email = email;
}
public String getFirstName () { return firstName; }
public String getLastName () { return lastName; }
public String getEmail () { return email; }
}
public class UserSelectExample {
public JSelect < User > createUserSelect () {
JSelect < User > userSelect = new JSelect <>();
userSelect . setPlaceholder ( "Select a user" );
userSelect . setSearchable ( true );
// Custom converter to display full name
userSelect . setConverter (user ->
user . getFirstName () + " " + user . getLastName ()
);
// Add users
userSelect . getItems (). addAll (
new User ( 1 , "John" , "Doe" , "john@example.com" ),
new User ( 2 , "Jane" , "Smith" , "jane@example.com" ),
new User ( 3 , "Bob" , "Johnson" , "bob@example.com" )
);
// Handle selection
userSelect . selectedItemProperty (). addListener ((obs, old, newVal) -> {
if (newVal != null ) {
System . out . println ( "Selected: " + newVal . getEmail ());
}
});
return userSelect;
}
}
Select with Custom Cell Factory
import com.jjarroyo.components.JSelect;
import javafx.scene.control.ListCell;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
public class CustomCellSelectExample {
public JSelect < User > createUserSelectWithIcons () {
JSelect < User > userSelect = new JSelect <>();
userSelect . setPlaceholder ( "Select a user" );
userSelect . setSearchable ( true );
// Custom converter
userSelect . setConverter (user ->
user . getFirstName () + " " + user . getLastName ()
);
// Custom cell factory with email subtitle
userSelect . setCellFactory (param -> new ListCell < User >() {
@ Override
protected void updateItem ( User user , boolean empty ) {
super . updateItem (user, empty);
if (empty || user == null ) {
setGraphic ( null );
setText ( null );
} else {
VBox content = new VBox ( 2 );
Label nameLabel = new Label (
user . getFirstName () + " " + user . getLastName ()
);
nameLabel . setStyle ( "-fx-font-weight: bold;" );
Label emailLabel = new Label ( user . getEmail ());
emailLabel . setStyle ( "-fx-font-size: 11px; -fx-text-fill: gray;" );
content . getChildren (). addAll (nameLabel, emailLabel);
setGraphic (content);
}
}
});
userSelect . getItems (). addAll (
new User ( 1 , "John" , "Doe" , "john@example.com" ),
new User ( 2 , "Jane" , "Smith" , "jane@example.com" )
);
return userSelect;
}
}
Programmatic Selection
JSelect < String > select = new JSelect <>();
select . getItems (). addAll ( "Option 1" , "Option 2" , "Option 3" );
// Set initial selection
select . setSelectedItem ( "Option 2" );
// For multiple selection
JSelect < String > multiSelect = new JSelect <>();
multiSelect . setMultiple ( true );
multiSelect . getItems (). addAll ( "A" , "B" , "C" , "D" );
multiSelect . getSelectedItems (). addAll ( "A" , "C" );
Behavior Details
Single Selection Mode
Click on an item to select it
Previously selected item is replaced
Popup closes after selection
Selected value displays in the trigger area
Multiple Selection Mode
Click items to toggle selection (checkboxes shown)
Multiple items can be selected
Popup remains open after selection
Selected items display as tags in trigger area
Click outside or press Escape to close
Search Functionality
Search field appears at top of dropdown when enabled
Filters items based on converter output
Case-insensitive matching
Updates in real-time as you type
Matches width of the trigger
Maximum height of 200px with scrolling
Auto-hides when clicking outside
Syncs stylesheets and dark mode from parent scene
Positioned 1px below trigger for seamless appearance
See Also