Cannot cast Object in JavaFX combobox


Question

I have this combobox which is user to display data by ID and Name:

public class Listobject extends Application
{


    public static void main(String[] args)
    {
        launch(args);
    }

    @Override
    public void start(Stage stage)
    {

        // Insert Some data

        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);

        ListGroupsObj ob = ListGroupsObj.newInstance().groupId(12).groupName("Group12");
        listGroups.getItems().addAll(ob);
        ListGroupsObj osb = ListGroupsObj.newInstance().groupId(13).groupName("Group13");
        listGroups.getItems().addAll(osb);
        ListGroupsObj oa = ListGroupsObj.newInstance().groupId(14).groupName("Group14");
        listGroups.getItems().addAll(oa);
        ListGroupsObj oz = ListGroupsObj.newInstance().groupId(15).groupName("Group15");
         listGroups.getItems().addAll(oz);


        // second way to add object
        listGroups.getItems().add(new ListGroupsObj(12, "Group 12"));

        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: " + arg2.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> lisGroups;

    public static class ListGroupsObj
    {

        private int groupId;
        private String groupName;

        public static ListGroupsObj newInstance()
        {
            return new ListGroupsObj();
        }

        public ListGroupsObj()
        {
        }

        public ListGroupsObj(int groupId, String groupName)
        {
            this.groupId = groupId;
            this.groupName = groupName;
        }

        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;
        }
    }
}

When I run the code I get this error:

Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: java.lang.String cannot be cast to listobject.Listobject$ListGroupsObj
    at listobject.Listobject$2.changed(Listobject.java:79)
    at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:347)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80)
    at javafx.beans.property.ReadOnlyObjectWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyObjectWrapper.java:176)
    at javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:142)
    at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
    at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:145)
    at javafx.scene.control.SelectionModel.setSelectedItem(SelectionModel.java:102)
    at javafx.scene.control.ComboBox$2.changed(ComboBox.java:221)
    at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:347)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80)
    at javafx.beans.property.ObjectPropertyBase.fireValueChangedEvent(ObjectPropertyBase.java:105)
    at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
    at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:145)
    at javafx.scene.control.ComboBoxBase.setValue(ComboBoxBase.java:167)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin.setTextFromTextFieldIntoComboBoxValue(ComboBoxListViewSkin.java:511)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin.access$200(ComboBoxListViewSkin.java:57)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin$6.changed(ComboBoxListViewSkin.java:416)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin$6.changed(ComboBoxListViewSkin.java:406)
    at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:347)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80)
    at javafx.beans.property.ReadOnlyBooleanPropertyBase.fireValueChangedEvent(ReadOnlyBooleanPropertyBase.java:72)
    at javafx.scene.Node$FocusedProperty.notifyListeners(Node.java:7486)
    at javafx.scene.Node.setFocused(Node.java:7537)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin$FakeFocusTextField.setFakeFocus(ComboBoxListViewSkin.java:696)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin$2.changed(ComboBoxListViewSkin.java:145)
    at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin$2.changed(ComboBoxListViewSkin.java:141)
    at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:347)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80)
    at javafx.beans.property.ReadOnlyBooleanPropertyBase.fireValueChangedEvent(ReadOnlyBooleanPropertyBase.java:72)
    at javafx.scene.Node$FocusedProperty.notifyListeners(Node.java:7486)
    at javafx.scene.Node.setFocused(Node.java:7537)
    at javafx.scene.Scene$KeyHandler.setWindowFocused(Scene.java:3856)
    at javafx.scene.Scene$KeyHandler$1.invalidated(Scene.java:3875)
    at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:135)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80)
    at javafx.beans.property.ReadOnlyBooleanWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyBooleanWrapper.java:178)
    at javafx.beans.property.ReadOnlyBooleanWrapper$ReadOnlyPropertyImpl.access$100(ReadOnlyBooleanWrapper.java:148)
    at javafx.beans.property.ReadOnlyBooleanWrapper.fireValueChangedEvent(ReadOnlyBooleanWrapper.java:144)
    at javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:110)
    at javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:143)
    at javafx.stage.Window.setFocused(Window.java:409)
    at com.sun.javafx.stage.WindowPeerListener.changedFocused(WindowPeerListener.java:59)
    at com.sun.javafx.tk.quantum.GlassWindowEventHandler.run(GlassWindowEventHandler.java:89)
    at com.sun.javafx.tk.quantum.GlassWindowEventHandler.run(GlassWindowEventHandler.java:39)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassWindowEventHandler.handleWindowEvent(GlassWindowEventHandler.java:130)
    at com.sun.glass.ui.Window.handleWindowEvent(Window.java:1235)
    at com.sun.glass.ui.Window.notifyFocus(Window.java:1210)
    at com.sun.glass.ui.win.WinWindow._setVisible(Native Method)
    at com.sun.glass.ui.Window.setVisible(Window.java:570)
    at com.sun.javafx.tk.quantum.WindowStage.setVisible(WindowStage.java:443)
    at javafx.stage.Window$9.invalidated(Window.java:776)
    at javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:109)
    at javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:143)
    at javafx.stage.Window.setShowing(Window.java:826)
    at javafx.stage.Window.hide(Window.java:851)
    at com.sun.javafx.stage.WindowCloseRequestHandler.dispatchBubblingEvent(WindowCloseRequestHandler.java:45)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:204)
    at com.sun.javafx.stage.WindowPeerListener.closing(WindowPeerListener.java:80)
    at com.sun.javafx.tk.quantum.GlassWindowEventHandler.run(GlassWindowEventHandler.java:113)
    at com.sun.javafx.tk.quantum.GlassWindowEventHandler.run(GlassWindowEventHandler.java:39)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassWindowEventHandler.handleWindowEvent(GlassWindowEventHandler.java:130)
    at com.sun.glass.ui.Window.handleWindowEvent(Window.java:1235)
    at com.sun.glass.ui.Window.notifyClose(Window.java:1139)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.access$300(WinApplication.java:39)
    at com.sun.glass.ui.win.WinApplication$4$1.run(WinApplication.java:112)
    at java.lang.Thread.run(Thread.java:744)

This line is the problem:

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: " + arg2.getGroupId() + " - " + arg2.getGroupName());
                }
            }
        });

Can you help me to fix this issue?

P.S I will add this converter:

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);
        }

    }
1
0
12/22/2013 9:06:47 PM

Accepted Answer

Peter use this code

import javafx.application.Application;
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;

/**
 *
 * @author reegan
 */
public class Listobject extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) {

        // Insert Some data

        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);

        ListGroupsObj ob = ListGroupsObj.newInstance().groupId(12).groupName("Group12");
        listGroups.getItems().addAll(ob);
        ListGroupsObj osb = ListGroupsObj.newInstance().groupId(13).groupName("Group13");
        listGroups.getItems().addAll(osb);
        ListGroupsObj oa = ListGroupsObj.newInstance().groupId(14).groupName("Group14");
        listGroups.getItems().addAll(oa);
        ListGroupsObj oz = ListGroupsObj.newInstance().groupId(15).groupName("Group15");
        listGroups.getItems().addAll(oz);


        // second way to add object
        listGroups.getItems().add(new ListGroupsObj(12, "Group 12"));

        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) {
//                    listGroups.setEditable(true);
//                    System.out.println("Selected Group: " + arg2.getGroupId() + " - " + arg2.getGroupName());
//                }
//            }
//        });


        listGroups.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>() {

            @Override
            public void changed(ObservableValue<? extends Object> ov, Object t, Object t1) {
//                 System.out.println("Selected Group:  " + t1.toString());
                 System.out.println("Selected Group : " + t1);
            }
        });

        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> lisGroups;

    public static class ListGroupsObj {

        private int groupId;
        private String groupName;

        public static ListGroupsObj newInstance() {
            return new ListGroupsObj();
        }

        public ListGroupsObj() {
        }

        public ListGroupsObj(int groupId, String groupName) {
            this.groupId = groupId;
            this.groupName = groupName;
        }

        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;
        }

    }
}
0
12/23/2013 5:50:21 AM

The problem is that your ComboBox is editable. When you edit it (or just click on it), it tries to set the value to the value in the TextField that is used as the editor. That value is a String: but you have created your ComboBox to store values of your type ListGroupsObj.

You either need to turn off the ability to type a value in (i.e. don't call listGroups.setEditable(true)), or you need to provide a converter by listGroups.setConverter(...).


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon