Set Date Picker time format - javafx

I have this example of Date Picker. Can you tell me how I can set the date format of the calendar?
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.DatePicker;
import javafx.stage.Stage;
import java.time.LocalDate;
public class PickerDemo extends Application {
#Override public void start(Stage stage) {
final DatePicker datePicker = new DatePicker(LocalDate.now());
datePicker.setOnAction(event -> {
LocalDate date = datePicker.getValue();
System.out.println("Selected date: " + date);
});
stage.setScene(
new Scene(datePicker)
);
stage.show();
}
public static void main(String[] args) { launch(args); }
}

This should do the trick:
datePicker.setConverter(new StringConverter<LocalDate>()
{
private DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofPattern("dd/MM/yyyy");
#Override
public String toString(LocalDate localDate)
{
if(localDate==null)
return "";
return dateTimeFormatter.format(localDate);
}
#Override
public LocalDate fromString(String dateString)
{
if(dateString==null || dateString.trim().isEmpty())
{
return null;
}
return LocalDate.parse(dateString,dateTimeFormatter);
}
});

Related

JxBrowser: How to implement 'save link as' within a ContextMenuHandler

I want to implement a 'save link as' option within a ContextMenuHandler.
But there is no browser function like loadURL(...) to force the Browser component to just start a download for the provided link.
__________________ EDITED__________________________
import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.ContextMenuHandler;
import com.teamdev.jxbrowser.chromium.ContextMenuParams;
import com.teamdev.jxbrowser.chromium.SavePageType;
import com.teamdev.jxbrowser.chromium.swing.BrowserView;
import java.awt.BorderLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class ContextMenuSample {
public static void main(String[] args) {
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
Browser browser = new Browser();
BrowserView view = new BrowserView(browser);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(view, BorderLayout.CENTER);
frame.setSize(700, 500);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
browser.setContextMenuHandler(new MyContextMenuHandler(view));
browser.loadURL("http://www.google.com");
}
private static class MyContextMenuHandler implements ContextMenuHandler {
private final JComponent component;
private MyContextMenuHandler(JComponent parentComponent) {
this.component = parentComponent;
}
private static JMenuItem createMenuItem(String title, final Runnable action) {
JMenuItem reloadMenuItem = new JMenuItem(title);
reloadMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
action.run();
}
});
return reloadMenuItem;
}
public void showContextMenu(final ContextMenuParams params) {
final JPopupMenu popupMenu = new JPopupMenu();
final Browser browser = params.getBrowser();
popupMenu.add(createMenuItem("Save As", new Runnable() {
#Override
public void run() {
Browser browser2 = new Browser();
browser2.loadURL(params.getLinkURL());
browser2.saveWebPage(params.getLinkText(), ".", SavePageType.COMPLETE_HTML);
}
}));
final Point location = params.getLocation();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
popupMenu.show(component, location.x, location.y);
}
});
}
}
}

JavaFX TableView custom cell rendering split menu button

i've a problem with a custom cell render in a java fx table view component. I'm able to render the split menu button, but is only rendered from second row of table.
Below i put the code created to generate that image.
SplitMenuButtonApp.java
package com.example.splimenubtn;
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.SplitMenuButton;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class SplitMenuButtonApp extends Application {
private class Contact {
private StringProperty firstName;
private StringProperty lastName;
public Contact() {}
public Contact(String fName, String lName) {
firstName = new SimpleStringProperty(fName);
lastName = new SimpleStringProperty(lName);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String fName) {
firstName.set(fName);
}
public StringProperty firstName() {
return firstName;
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String lName) {
lastName.set(lName);
}
public StringProperty lastName() {
return lastName;
}
}
private ObservableList<Contact> data;
protected List<MenuItemFactory<Contact>> menuItemsList;
private TableView<Contact> table;
#Override
public void start(Stage primaryStage) throws Exception {
// Init data list
data = FXCollections.observableArrayList();
data.add(new Contact("Mickey", "Mouse"));
data.add(new Contact("Donald", "Duck"));
data.add(new Contact("Fantasy", "Name"));
initMenuButton();
SplitMenuButtonFactory<Contact> sMBtn = new SplitMenuButtonFactory<>();
sMBtn.setMenuItems(menuItemsList);
SplitMenuButton actions = sMBtn.buildButton();
// Build the list
table = new TableView<>();
TableColumn<Contact, String> col = new TableColumn<>("First Name");
col.setCellValueFactory(c -> c.getValue().firstName);
table.getColumns().add(col);
col = new TableColumn<>("Last Name");
col.setCellValueFactory(c -> c.getValue().lastName);
table.getColumns().add(col);
TableColumn<Contact, SplitMenuButton> aCol = new TableColumn<>("Action");
aCol.setCellValueFactory(new PropertyValueFactory<>(""));
aCol.setCellFactory(new ButtonCellFactory<>(actions));
table.getColumns().add(aCol);
table.setItems(data);
AnchorPane root = new AnchorPane();
AnchorPane.setTopAnchor(table, 5.0);
AnchorPane.setRightAnchor(table, 5.0);
AnchorPane.setBottomAnchor(table, 5.0);
AnchorPane.setLeftAnchor(table, 5.0);
root.getChildren().add(table);
Scene s = new Scene(root, 600d, 300d);
primaryStage.setScene(s);
primaryStage.setTitle("Split menu button on table row");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
private void initMenuButton() {
if (menuItemsList == null) {
menuItemsList = new ArrayList<>();
menuItemsList.add(new MenuItemFactory<Contact>(MenuItemActions.EDIT, "Edit", true).setDataList(table));
menuItemsList.add(new MenuItemFactory<Contact>(MenuItemActions.DELETE, "Delete", false).setDataList(table));
}
}
}
MenuItemActions.java
package com.example.splimenubtn;
public enum MenuItemActions {
/**
* Detail item
*/
DETAILS,
/**
* Edit/Update item
*/
EDIT,
/**
* Delete item
*/
DELETE;
}
MenuItemFactory.java
package com.example.splimenubtn;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableView;
public class MenuItemFactory<S> {
private MenuItemActions itemType;
private String itemLbl;
private TableView<S> table;
private boolean defaultAction;
public MenuItemFactory() {}
public MenuItemFactory(MenuItemActions itemType, String itemLabel, boolean dA) {
this.itemType = itemType;
itemLbl = itemLabel;
defaultAction = dA;
}
public MenuItemFactory<S> setDataList(TableView<S> t) {
table = t;
return this;
}
public boolean isDefault() {
return defaultAction;
}
public MenuItem buildMenuItem() {
MenuItem mI = new MenuItem();
switch (itemType) {
case DETAILS:
mI.setText(itemLbl);
mI.setOnAction(handleDetails());
break;
case EDIT:
mI.setText(itemLbl);
mI.setOnAction(handleEdit());
break;
case DELETE:
mI.setText(itemLbl);
mI.setOnAction(handleDelete());
break;
default:
break;
}
return mI;
}
private EventHandler<ActionEvent> handleDetails() {
return new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent aE) {
System.out.println("*** DETAIL REQUESTED ***");
}
};
}
private EventHandler<ActionEvent> handleEdit() {
return new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent aE) {
System.out.println("*** EDIT REQUESTED ***");
}
};
}
private EventHandler<ActionEvent> handleDelete() {
return new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent aE) {
System.out.println("*** DELETE REQUESTED ***");
}
};
}
}
ButtonCellFactory.java
package com.example.splimenubtn;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.SplitMenuButton;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.util.Callback;
public class ButtonCellFactory<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>> {
private SplitMenuButton btn;
public ButtonCellFactory() {}
public ButtonCellFactory(SplitMenuButton b) {
btn = b;
}
#Override
public TableCell<S, T> call(TableColumn<S, T> param) {
return new TableCell<S, T>() {
#Override
public void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
setText(null);
} else {
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
setGraphic(btn);
}
}
};
}
}
SpliMenuButtonFactory.java
package com.example.splimenubtn;
import java.util.List;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SplitMenuButton;
public class SplitMenuButtonFactory<T> {
private List<MenuItemFactory<T>> menuItems;
public SplitMenuButtonFactory() {}
public SplitMenuButtonFactory<T> setMenuItems(List<MenuItemFactory<T>> items) {
menuItems = items;
return this;
}
public SplitMenuButton buildButton() {
SplitMenuButton menuBtn = new SplitMenuButton();
for (MenuItemFactory<?> mIF : menuItems) {
MenuItem btn = mIF.buildMenuItem();
if (mIF.isDefault()) {
menuBtn.setText(btn.getText());
menuBtn.setOnAction(btn.getOnAction());
}
menuBtn.getItems().add(btn);
}
return menuBtn;
}
}
As you see in the image, with this code i'm able to create the spli menu button and add it to ta table, but is only rendered on last row.
I need suggestion to render the split menu button in the other row, any help is appreciated.
Cause you have use the same button in every cell, So it's set a button only last of the cell Value.
Remove this line in SplitMenuButtonApp class
SplitMenuButton actions = sMBtn.buildButton();
And replace this line
aCol.setCellFactory(new ButtonCellFactory<>(actions));
To below code
Callback<TableColumn<Contact, SplitMenuButton>, TableCell<Contact, SplitMenuButton>> actionsCol = new Callback<TableColumn<Contact, SplitMenuButton>, TableCell<Contact, SplitMenuButton>>() {
#Override
public TableCell call(final TableColumn<Contact, SplitMenuButton> param) {
final TableCell<Contact, SplitMenuButton> cell = new TableCell<Contact, SplitMenuButton>() {
SplitMenuButton actions = sMBtn.buildButton();
#Override
public void updateItem(SplitMenuButton item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
setText(null);
} else {
setGraphic(actions);
setText(null);
}
}
};
return cell;
}
};
aCol.setCellFactory(actionsCol);
I hope this code is working for you:)

Allow user to only select Mondays in DatePicker

I am working on a javafx project and I have included a DatePicker. I want to make the user only be able to select Mondays
DatePicker startDate = new DatePicker();
Any Ideas if it's possible?
There are two things you need to do:
Veto the change if the user changes the date in the text field to a date that is not a Monday. You can do this with the converter property of the DatePicker.
Disable all the cells in the popup that are not Mondays. You can do this with the dayCellFactory.
Simple example:
import java.time.DayOfWeek;
import java.time.LocalDate;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.DateCell;
import javafx.scene.control.DatePicker;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.StringConverter;
public class DatePickerMondaysOnly extends Application {
#Override
public void start(Stage primaryStage) {
DatePicker datePicker = new DatePicker();
StringConverter<LocalDate> defaultConverter = datePicker.getConverter();
datePicker.setConverter(new StringConverter<LocalDate>() {
#Override
public String toString(LocalDate object) {
return defaultConverter.toString(object);
}
#Override
public LocalDate fromString(String string) {
LocalDate date = defaultConverter.fromString(string);
if (date.getDayOfWeek() == DayOfWeek.MONDAY) {
return date ;
} else {
// not a Monday. Revert to previous value.
// You could also, e.g., return the closest Monday here.
return datePicker.getValue();
}
}
});
datePicker.setDayCellFactory(dp -> new DateCell() {
#Override
public void updateItem(LocalDate item, boolean empty) {
super.updateItem(item, empty);
setDisable(empty || item.getDayOfWeek() != DayOfWeek.MONDAY);
}
});
// Just for debugging: make sure we only see Mondays:
datePicker.valueProperty().addListener((obs, oldDate, newDate) -> {
if (newDate.getDayOfWeek() != DayOfWeek.MONDAY) {
System.out.println("WARNING: date chosen was not a Monday");
}
System.out.println(newDate + " (" + newDate.getDayOfWeek()+")");
});
StackPane root = new StackPane(datePicker);
root.setPadding(new Insets(20));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Adding currency symbol to tableview but remove on edit cell

I already know how I have to manipulate the table cell using a table cell factory callback. I added a currency symbol to the cell to make it look neat. (i.e. € 5,00 instead of 5,00) The thing is, when i double click on the cell i want that symbol to be removed. But for the heck of it, I'm unable to find how i am able to manipulate the textfield again to remove that currency symbol and bring it back in when the user committed the edit. Basically what I try to do is something similar when editing a cell in Excel :).
Any chance someone can help me out with a little basic example? Do I need to use the OnEditStart event?
Any time you want to configure how an item in a cell is displayed, without changing the actual data, you should use a custom TableCell. Here is an example that exhibits the behavior you want:
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.function.UnaryOperator;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.TextFormatter.Change;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.util.StringConverter;
public class CurrencyCell<T> extends TableCell<T, Double> {
private final TextField textField ;
private final NumberFormat format = DecimalFormat.getCurrencyInstance();
private final DecimalFormat textFieldFormat = new DecimalFormat("0.00");
public CurrencyCell() {
this.textField = new TextField();
StringConverter<Double> converter = new StringConverter<Double>() {
#Override
public String toString(Double object) {
return object == null ? "" : textFieldFormat.format(object) ;
}
#Override
public Double fromString(String string) {
try {
return string.isEmpty() ? 0.0 : textFieldFormat.parse(string).doubleValue();
} catch (ParseException e) {
e.printStackTrace();
return 0.0 ;
}
}
};
UnaryOperator<Change> filter = (Change change) -> {
String newText = change.getControlNewText() ;
if (newText.isEmpty()) {
return change ;
}
try {
textFieldFormat.parse(newText);
return change ;
} catch (ParseException exc) {
return null ;
}
};
TextFormatter<Double> textFormatter = new TextFormatter<Double>(converter, 0.0, filter);
textField.setTextFormatter(textFormatter);
textField.setOnAction(e -> commitEdit(converter.fromString(textField.getText())));
textField.addEventFilter(KeyEvent.KEY_PRESSED, e -> {
if (e.getCode() == KeyCode.ESCAPE) {
cancelEdit();
}
});
setGraphic(textField);
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
#Override
protected void updateItem(Double item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setContentDisplay(ContentDisplay.TEXT_ONLY);
} else if (isEditing()) {
textField.setText(item.toString());
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
} else {
setText(format.format(item));
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
#Override
public void startEdit() {
super.startEdit();
textField.setText(textFieldFormat.format(getItem()));
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
textField.requestFocus();
textField.selectAll();
}
#Override
public void cancelEdit() {
super.cancelEdit();
setText(format.format(getItem()));
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
#Override
public void commitEdit(Double newValue) {
super.commitEdit(newValue);
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
And here's an example using it:
import java.util.Locale ;
import java.util.Random;
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
public class CurrencyCellTest extends Application {
#Override
public void start(Stage primaryStage) {
TableView<Item> table = new TableView<>();
table.setEditable(true);
table.getColumns().add(column("Item", Item::nameProperty));
TableColumn<Item, Double> priceCol = column("Price", item -> item.priceProperty().asObject());
table.getColumns().add(priceCol);
priceCol.setCellFactory(tc -> new CurrencyCell<>());
Random rng = new Random();
for (int i = 1; i <= 100; i++) {
table.getItems().add(new Item("Item "+i, rng.nextInt(10000)/100.0));
}
primaryStage.setScene(new Scene(table, 600, 600));
primaryStage.show();
}
private static <S,T> TableColumn<S,T> column(String title, Function<S, Property<T>> property) {
TableColumn<S,T> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
return col ;
}
public static class Item {
private final StringProperty name = new SimpleStringProperty();
private final DoubleProperty price = new SimpleDoubleProperty();
public Item(String name, double price) {
setName(name);
setPrice(price);
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final DoubleProperty priceProperty() {
return this.price;
}
public final double getPrice() {
return this.priceProperty().get();
}
public final void setPrice(final double price) {
this.priceProperty().set(price);
}
}
public static void main(String[] args) {
// for testing:
Locale.setDefault(new Locale("NL", "nl"));
launch(args);
}
}

Cast String in JavaFX ComboBox

I'm trying to use this to select a value from a Custom Combo Box:
import java.util.List;
import javafx.application.Application;
import static javafx.application.Application.launch;
import static javafx.application.Application.launch;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.StringConverter;
public class MainApp extends Application
{
public static void main(String[] args)
{
launch(args);
}
#Override
public void start(Stage stage)
{
final ComboBox<ListGroupsObj> listGroups = new ComboBox();
listGroups.setButtonCell(new GroupListCell());
listGroups.setCellFactory(new Callback<ListView<ListGroupsObj>, ListCell<ListGroupsObj>>()
{
#Override
public ListCell<ListGroupsObj> call(ListView<ListGroupsObj> p)
{
return new GroupListCell();
}
});
listGroups.setEditable(true);
listGroups.setConverter..............
// Insert Some data
ListGroupsObj ob = ListGroupsObj.newInstance().groupId(12).groupName("Test");
listGroups.getItems().addAll(ob);
ListGroupsObj osb = ListGroupsObj.newInstance().groupId(13).groupName("Test2");
listGroups.getItems().addAll(osb);
listGroups.setValue(ob);
// Display the selected Group
listGroups.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<ListGroupsObj>()
{
#Override
public void changed(ObservableValue<? extends ListGroupsObj> arg0, ListGroupsObj arg1, ListGroupsObj arg2)
{
if (arg2 != null)
{
System.out.println("Selected Group: " + arg1.getGroupId() + " - " + arg2.getGroupName());
}
}
});
final StackPane layout = new StackPane();
layout.getChildren().add(listGroups);
layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 15;");
stage.setScene(new Scene(layout));
stage.show();
}
class GroupListCell extends ListCell<ListGroupsObj>
{
#Override
protected void updateItem(ListGroupsObj item, boolean empty)
{
super.updateItem(item, empty);
if (item != null)
{
setText(item.getGroupId() + " - " + item.getGroupName());
}
}
}
private List<ListGroupsObj> listGroups;
public static class ListGroupsObj
{
private int groupId;
private String groupName;
public static ListGroupsObj newInstance()
{
return new ListGroupsObj();
}
public ListGroupsObj()
{
}
public ListGroupsObj groupId(int groupId)
{
this.groupId = groupId;
return this;
}
public ListGroupsObj groupName(String groupName)
{
this.groupName = groupName;
return this;
}
public int getGroupId()
{
return groupId;
}
public String getGroupName()
{
return groupName;
}
#Override
public String toString()
{
return groupId + " - " + groupName;
}
}
public class GroupConverter extends StringConverter<ListGroupsObj>
{
#Override
public String toString(ListGroupsObj obj)
{
return obj.getGroupId() + " - " + obj.getGroupName();
}
#Override
public ListGroupsObj fromString(String obj)
{
//TODO when you type for example "45 - NextGroup" you want to take only tyhe number"
return ListGroupsObj.newInstance().groupName(obj);
}
}
}
I get this error when I click outside of the comboBox:
Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: java.lang.String cannot be cast to com.selectmenuexample.MainApp$ListGroupsObj
I found that this can be done using convertor but I'm now aware how to use it. Can you help with this implementation?
Here is what is wrong:
You called your ComboBox listGroups and your List of Items listGroups. So in your start code, you were hiding that variable. So I removed that useless variable since you can manipulate Items directly in the ComboBox.
You had basically three methods/variable doing the exact same things. Converting your Object into a String with a "-" between them. So I removed the GroupConverter and the custom cellFactory. You don't need them because you already have your "toString()" method in your ListGroupsObj which is doing the job.
Then you misunderstood how the ComboBox is working. If it's editable, the ComboBox will allow something to be typed inside the TextField. That's where the StringConverter comes. It will allow you to make the conversion between a String and your ListGroupsObj and the way around.
In order to go from a ListGroupsObj to a String, simply call the "toString()" method on your object.
But in the way around, you should either create a new ListGroupsObj, or verify that what's inside the ComboBox is not already one item of yours. For example, if you select an Item in the comboBox, the fromString() will be called. But you don't want to create a new ListGroupsObj, you just want to isolate the ListGroupsObj inside your items List and returns it.
Now, you have the guaranty that a call to getValue() on your ComboBox will always return an ListGroupsObj object since you have provided a custom and valid StringConverter.
Here is a simplified and working version of your code :
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.StringConverter;
public class MainApp extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
final ComboBox<ListGroupsObj> comboBox = new ComboBox();
comboBox.setEditable(true);
comboBox.setConverter(new StringConverter<ListGroupsObj>() {
#Override
public String toString(ListGroupsObj obj) {
return obj.toString();
}
#Override
public ListGroupsObj fromString(String obj) {
//Here we try to identify if the given String actually represents one item of our list
for(ListGroupsObj tempObj:comboBox.getItems()){
if(tempObj.toString().equals(obj)){
return tempObj;
}
}
//If not we just create a new one
return ListGroupsObj.newInstance().groupName(obj);
}
});
// Insert Some data
ListGroupsObj ob = ListGroupsObj.newInstance().groupId(12).groupName("Test");
comboBox.getItems().addAll(ob);
ListGroupsObj osb = ListGroupsObj.newInstance().groupId(13).groupName("Test2");
comboBox.getItems().addAll(osb);
comboBox.setValue(ob);
final StackPane layout = new StackPane();
layout.getChildren().add(comboBox);
layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 15;");
stage.setScene(new Scene(layout));
stage.show();
}
public static class ListGroupsObj {
private int groupId;
private String groupName;
public static ListGroupsObj newInstance() {
return new ListGroupsObj();
}
public ListGroupsObj() {
}
public ListGroupsObj groupId(int groupId) {
this.groupId = groupId;
return this;
}
public ListGroupsObj groupName(String groupName) {
this.groupName = groupName;
return this;
}
public int getGroupId() {
return groupId;
}
public String getGroupName() {
return groupName;
}
#Override
public String toString() {
return groupId + " - " + groupName;
}
}
}
PS: The issue was already raised in the official JavaFX issue Tracker, I'll leave the link here since there is another example in the ticket (login required) : https://javafx-jira.kenai.com/browse/RT-29118

Resources