2013-10-07 68 views
2

我正在使用試圖使用javafx組合框與單元格工廠來呈現列表,我在我的CellList的覆蓋updateItem()上使用setText,但我發現當我更改了底層模型的值,這不會影響組合框上的已部署列表。所以我試圖讓它綁定這兩個屬性和它的作品,但當嘗試清除選擇我有一個例外。這是代碼:Javafx組合框綁定值無法設置異常

import javafx.application.Application; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.scene.Scene; 
import javafx.scene.control.*; 
import javafx.scene.layout.*; 
import javafx.stage.Stage; 
import javafx.util.Callback; 

public class BasicComboBoxSample extends Application { 
    public static void main(String[] args) { launch(args); } 

    @Override public void start(Stage stage) { 
     final Employee john = new Employee("John"); 
     final Employee jill = new Employee("Jill"); 
     final Employee jack = new Employee("Jack"); 

     final ComboBox<Employee> cboEmployees = new ComboBox(); 

     cboEmployees.getItems().addAll(john, jill, jack); 
     cboEmployees.setValue(jill); 

     Button b = new Button("ChangeName"); 
     b.setOnAction(new EventHandler<ActionEvent>() { 
      @Override 
      public void handle(ActionEvent actionEvent) { 
       john.setName("Maria"); 
      } 
     }); 

     Button c = new Button("Clear"); 
     c.setOnAction(new EventHandler<ActionEvent>() { 
      @Override 
      public void handle(ActionEvent actionEvent) { 
       cboEmployees.getSelectionModel().clearSelection(); 
      } 
     }); 

     Button d = new Button("Select First"); 
     d.setOnAction(new EventHandler<ActionEvent>() { 
      @Override 
      public void handle(ActionEvent actionEvent) { 
       cboEmployees.getSelectionModel().select(john); 
      } 
     }); 

     Callback<ListView<Employee>, ListCell<Employee>> cellFactory = new Callback<ListView<Employee>, ListCell<Employee>>() { 
      @Override 
      public ListCell<Employee> call(ListView<Employee> listView) { 
       return new EmployeeListCell(); //To change body of implemented methods use File | Settings | File Templates. 
      } 
     }; 

     cboEmployees.setButtonCell(new EmployeeListCell()); 
     cboEmployees.setCellFactory(cellFactory); 

     final StackPane layout = new StackPane(); 
     VBox v = new VBox(); 

     v.getChildren().add(cboEmployees); 
     v.getChildren().add(b); 
     v.getChildren().add(c); 
     v.getChildren().add(d); 
     layout.getChildren().add(v); 

     layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 15;"); 
     stage.setScene(new Scene(layout)); 
     stage.show(); 
    } 

    class Employee { 
     public Employee(String name) { this.setName(name); } 
     private SimpleStringProperty name = new SimpleStringProperty(""); 

     String getName() { 
      return name.get(); 
     } 

     SimpleStringProperty nameProperty() { 
      return name; 
     } 

     void setName(String name) { 
      this.name.set(name); 
     } 
    } 


    public class EmployeeListCell extends ListCell<Employee> { 

     @Override 
     protected void updateItem(Employee emp, boolean b) { 
      super.updateItem(emp, b); 
      if(emp != null){ 
       textProperty().bind(emp.nameProperty()); 
      } 
     } 
    } 
} 

而唯一的例外是:

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: A bound value cannot be set. 
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:157) 
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:67) 
at javafx.beans.property.StringProperty.setValue(StringProperty.java:84) 
at javafx.scene.control.Labeled.setText(Labeled.java:135) 
at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin.updateDisplayText(ComboBoxListViewSkin.java:420) 
at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin.updateDisplayNode(ComboBoxListViewSkin.java:399) 
at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin.getDisplayNode(ComboBoxListViewSkin.java:229) 
at com.sun.javafx.scene.control.skin.ComboBoxBaseSkin.updateDisplayArea(ComboBoxBaseSkin.java:125) 
at com.sun.javafx.scene.control.skin.ComboBoxBaseSkin.handleControlPropertyChanged(ComboBoxBaseSkin.java:120) 
at com.sun.javafx.scene.control.skin.ComboBoxListViewSkin.handleControlPropertyChanged(ComboBoxListViewSkin.java:198) 
at com.sun.javafx.scene.control.skin.SkinBase$3.changed(SkinBase.java:282) 
at javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:107) 
at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:367) 
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100) 
at javafx.beans.property.ObjectPropertyBase.fireValueChangedEvent(ObjectPropertyBase.java:123) 
at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:130) 
at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:163) 
at javafx.scene.control.ComboBoxBase.setValue(ComboBoxBase.java:148) 
at javafx.scene.control.ComboBox.updateValue(ComboBox.java:416) 
at javafx.scene.control.ComboBox.access$300(ComboBox.java:166) 
at javafx.scene.control.ComboBox$6.changed(ComboBox.java:401) 
at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:367) 
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100) 
at javafx.beans.property.ReadOnlyObjectWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyObjectWrapper.java:195) 
at javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:161) 
at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:130) 
at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:163) 
at javafx.scene.control.SelectionModel.setSelectedItem(SelectionModel.java:101) 
at javafx.scene.control.ComboBox$ComboBoxSelectionModel$1.invalidated(ComboBox.java:448) 
at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:155) 
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100) 
at javafx.beans.property.ReadOnlyIntegerWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyIntegerWrapper.java:195) 
at javafx.beans.property.ReadOnlyIntegerWrapper.fireValueChangedEvent(ReadOnlyIntegerWrapper.java:161) 
at javafx.beans.property.IntegerPropertyBase.markInvalid(IntegerPropertyBase.java:130) 
at javafx.beans.property.IntegerPropertyBase.set(IntegerPropertyBase.java:163) 
at javafx.scene.control.SelectionModel.setSelectedIndex(SelectionModel.java:67) 
at javafx.scene.control.SingleSelectionModel.updateSelectedIndex(SingleSelectionModel.java:208) 
at javafx.scene.control.SingleSelectionModel.clearSelection(SingleSelectionModel.java:67) 
at de.thomasbolz.javafx.BasicComboBoxSample$2.handle(BasicComboBoxSample.java:45) 
at de.thomasbolz.javafx.BasicComboBoxSample$2.handle(BasicComboBoxSample.java:42) 
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:69) 
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217) 
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170) 
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38) 
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37) 
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92) 
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35) 
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92) 
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53) 
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:28) 
at javafx.event.Event.fireEvent(Event.java:171) 
at javafx.scene.Node.fireEvent(Node.java:6863) 
at javafx.scene.control.Button.fire(Button.java:179) 
at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:193) 
at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:336) 
at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:329) 
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:64) 
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217) 
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170) 
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38) 
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37) 
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92) 
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35) 
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92) 
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35) 
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92) 
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53) 
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:33) 
at javafx.event.Event.fireEvent(Event.java:171) 
at javafx.scene.Scene$MouseHandler.process(Scene.java:3328) 
at javafx.scene.Scene$MouseHandler.process(Scene.java:3168) 
at javafx.scene.Scene$MouseHandler.access$1900(Scene.java:3123) 
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1563) 
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2265) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:250) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:173) 
at java.security.AccessController.doPrivileged(Native Method) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:292) 
at com.sun.glass.ui.View.handleMouseEvent(View.java:528) 
at com.sun.glass.ui.View.notifyMouse(View.java:922) 
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method) 
at com.sun.glass.ui.gtk.GtkApplication$3$1.run(GtkApplication.java:82) 
at java.lang.Thread.run(Thread.java:722) 

回答

3

您需要取消綁定的情況下,EMP是空的textProperty

1

添加條件EmployeeListCell類

else { 
textProperty().unbind(); 
}