2017-01-10 97 views
0

我試圖創建一個TableView,其中包含Student對象和Classroom對象。現在,我想要一個ChoiceBoxStudents從一個Classroom換成另一個。 。使用自定義可編輯單元格創建JFX TableView的問題

下面的代碼

public class ChoiceBoxCell extends TableCell<Student, Classroom> { 


    ChoiceBox<Classroom> classroomChoiceBox = new ChoiceBox<>(); 

    public ChoiceBoxCell(ObservableList<Classroom> classroomObservableList) { 
     ObservableList<Classroom> classroomObservableListList = classroomObservableList; 
     classroomChoiceBox.setItems(classroomObservableListList); 

     classroomChoiceBox.getSelectionModel().selectedIndexProperty().addListener((obs, oldValue, newValue) -> { 
      Classroom value = classroomChoiceBox.getItems().get((int) newValue); 
      classroomChoiceBox.setValue(value); 
      processEdit(value); 
     }); 
    } 
    private void processEdit(Classroom value) { 
     commitEdit(value); 
     classroomChoiceBox.setValue(value); 
     setGraphic(classroomChoiceBox); 
    } 

    @Override 
    public void cancelEdit() { 
     super.cancelEdit(); 
     setGraphic(classroomChoiceBox); 
    } 

    @Override 
    public void commitEdit(Classroom value) { 
     super.commitEdit(value); 
     classroomChoiceBox.setValue(value); 
     setGraphic(classroomChoiceBox); 
    } 

    @Override 
    public void startEdit() { 
     super.startEdit(); 
     Classroom value = getItem(); 
     if (value != null) { 
      classroomChoiceBox.setValue(value); 
      setGraphic(classroomChoiceBox); 
     } 
    } 

    @Override 
    protected void updateItem(Classroom item, boolean empty) { 
     super.updateItem(item, empty); 
     if (item == null || empty) { 
      classroomChoiceBox.setValue(item); 
      setGraphic(classroomChoiceBox); 
     } else { 
      classroomChoiceBox.setValue(item); 
      setGraphic(classroomChoiceBox); 
     } 
    } 
} 

在我的TableView類

列表classroomList =新ClassroomDao()getAllClasses();ObservableList classroomObservableList = FXCollections.observableArrayList(classroomList);

classroomNameColumn.setPrefWidth(columnSize); 
classroomNameColumn.setCellValueFactory(cdf -> cdf.getValue().classroomProperty()); 
classroomNameColumn.setCellFactory(column -> new ChoiceBoxCell(classroomObservableList)); 
classroomNameColumn.setEditable(true); 

我得到以下異常

Exception in thread "JavaFX Application Thread" java.lang.ArrayIndexOutOfBoundsException: -1 
at java.util.ArrayList.elementData(ArrayList.java:418) 
at java.util.ArrayList.get(ArrayList.java:431) 
at com.sun.javafx.collections.ObservableListWrapper.get(ObservableListWrapper.java:89) 
at view.adminAccess.studentOverview.ChoiceBoxCell.lambda$new$0(ChoiceBoxCell.java:20) 
at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:361) 
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81) 
at javafx.beans.property.ReadOnlyIntegerWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyIntegerWrapper.java:176) 
at javafx.beans.property.ReadOnlyIntegerWrapper.fireValueChangedEvent(ReadOnlyIntegerWrapper.java:142) 
at javafx.beans.property.IntegerPropertyBase.markInvalid(IntegerPropertyBase.java:113) 
at javafx.beans.property.IntegerPropertyBase.set(IntegerPropertyBase.java:147) 
at javafx.scene.control.SelectionModel.setSelectedIndex(SelectionModel.java:68) 
at javafx.scene.control.SingleSelectionModel.select(SingleSelectionModel.java:114) 
at javafx.scene.control.ChoiceBox$4.invalidated(ChoiceBox.java:331) 
at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:111) 
at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:146) 
at javafx.scene.control.ChoiceBox.setValue(ChoiceBox.java:336) 
at view.adminAccess.studentOverview.ChoiceBoxCell.updateItem(ChoiceBoxCell.java:58) 
at view.adminAccess.studentOverview.ChoiceBoxCell.updateItem(ChoiceBoxCell.java:10) 
at javafx.scene.control.TableCell.updateItem(TableCell.java:639) 
at javafx.scene.control.TableCell.indexChanged(TableCell.java:468) 
at javafx.scene.control.IndexedCell.updateIndex(IndexedCell.java:116) 
at com.sun.javafx.scene.control.skin.TableRowSkinBase.requestCellUpdate(TableRowSkinBase.java:659) 
at com.sun.javafx.scene.control.skin.TableRowSkinBase.lambda$init$497(TableRowSkinBase.java:159) 
at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:137) 
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81) 
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:146) 
at javafx.scene.control.Cell.setItem(Cell.java:403) 
at javafx.scene.control.Cell.updateItem(Cell.java:670) 
at javafx.scene.control.TableRow.updateItem(TableRow.java:268) 
at javafx.scene.control.TableRow.indexChanged(TableRow.java:225) 
at javafx.scene.control.IndexedCell.updateIndex(IndexedCell.java:116) 
at com.sun.javafx.scene.control.skin.VirtualFlow.releaseCell(VirtualFlow.java:1807) 
at com.sun.javafx.scene.control.skin.VirtualFlow.getCellLength(VirtualFlow.java:1881) 
at com.sun.javafx.scene.control.skin.VirtualFlow.computeViewportOffset(VirtualFlow.java:2528) 
at com.sun.javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:1189) 
at javafx.scene.Parent.layout(Parent.java:1079) 
at javafx.scene.Parent.layout(Parent.java:1085) 
at javafx.scene.Parent.layout(Parent.java:1085) 
at javafx.scene.Parent.layout(Parent.java:1085) 
at javafx.scene.Parent.layout(Parent.java:1085) 
at javafx.scene.Scene.doLayoutPass(Scene.java:552) 
at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2397) 
at com.sun.javafx.tk.Toolkit.lambda$runPulse$31(Toolkit.java:355) 
at java.security.AccessController.doPrivileged(Native Method) 
at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:354) 
at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:381) 
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:510) 
at com.sun.javafx.tk.quantum.PaintCollector.liveRepaintRenderJob(PaintCollector.java:320) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler$ViewEventNotification.run(GlassViewEventHandler.java:788) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler$ViewEventNotification.run(GlassViewEventHandler.java:749) 
at java.security.AccessController.doPrivileged(Native Method) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleViewEvent$369(GlassViewEventHandler.java:828) 
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleViewEvent(GlassViewEventHandler.java:827) 
at com.sun.glass.ui.View.handleViewEvent(View.java:539) 
at com.sun.glass.ui.View.notifyResize(View.java:875) 
at com.sun.glass.ui.win.WinWindow._setBounds(Native Method) 
at com.sun.glass.ui.Window.setBounds(Window.java:572) 
at com.sun.javafx.tk.quantum.WindowStage.setBounds(WindowStage.java:318) 
at javafx.stage.Window$TKBoundsConfigurator.apply(Window.java:1274) 
at javafx.stage.Window$TKBoundsConfigurator.pulse(Window.java:1290) 
at com.sun.javafx.tk.Toolkit.lambda$runPulse$31(Toolkit.java:355) 
at java.security.AccessController.doPrivileged(Native Method) 
at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:354) 
at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:378) 
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:510) 
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490) 
at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$405(QuantumToolkit.java:319) 
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95) 
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) 
at com.sun.glass.ui.win.WinApplication.lambda$null$149(WinApplication.java:191) 
at java.lang.Thread.run(Thread.java:745) 

This是它的樣子。它看起來像最後一個單元格試圖適合表中的每一行,並且使用ChoiceBox.

如何才能將此限制僅限於其中包含數據的行?

編輯:額外問題

我現在使用的部分代碼。

classroomChoiceBox.getSelectionModel().selectedItemProperty().addListener((obs, oldValue, newValue) -> { 
     if (newValue != null) { 
      processEdit(newValue); 
     } 
    }); 

@Override 
public void commitEdit(Classroom value) { // always gets executed 
    super.commitEdit(value); 
    Student student = (Student) getTableRow().getItem(); 
    student.setClassroom(value); 
    new StudentDao().updateStudent(student); // students get updated on creation of the table 
    classroomChoiceBox.setValue(value); 
    setGraphic(classroomChoiceBox); 
} 

問題是每個Student在創建表時都會更新。

+0

在您的問題中發佈完整的堆棧跟蹤。 –

+0

@James_D編輯,這就是它所顯示的。 –

+0

大概第20行是'Classroom value = classroomChoiceBox.getSelectionModel()...'? –

回答

0

如果未選擇任何內容(請參閱docs),選定模型中的選定索引設置爲-1。由於-1不在列表中的有效索引,你需要檢查這種情況:

classroomChoiceBox.getSelectionModel().selectedIndexProperty().addListener((obs, oldValue, newValue) -> { 
    int index = newValue.intValue(); 
    if (index >= 0) { 
     Classroom value = classroomChoiceBox.getItems().get(index); 

     // what is the point of the next line? 
     // surely this is the value in the choice box already??? 
     classroomChoiceBox.setValue(value); 

     processEdit(value); 
    } 
}); 

當然,它可能是更容易只是直接從選擇模型中獲得的,而不是獲取其指標值,:

classroomChoiceBox.getSelectionModel().selectedItemProperty().addListener((obs, oldValue, newValue) -> { 
    if (newValue != null) { /* don't know if you care if this is null... */ 
     processEdit(newValue); 
    } 
}); 

您所看到的空單元格的選擇框的原因是你明確地設置圖形的選擇框空細胞,在細胞的updateItem方法。我假設(因爲if塊與else塊相同),這只是某種類型的複製粘貼錯誤。

+0

太好了,非常感謝。第一個解決方案完美地工作(第二個解決方案不像newValue是'Number',我需要一個'Classroom'對象。不管怎麼說,沒關係,因爲第一個解決方案沒有任何問題)。 –

+0

@HonzaŠtefánik顯然你沒有正確地閱讀答案。如果將'newValue'從'selectedIndexProperty'改爲'selectedItemProperty','newValue'是'Classroom',而不是'Number'。 –

+0

哦,事實證明我甚至不需要'if(index> = 0)'。那可能是錯誤的'setGraphic'。是的,我不需要'classroomChoiceBox.setValue(value);'。再次感謝。 –

相關問題