2015-01-07 2 views
3

В настоящее время я получаю сообщение об ошибке, которое я не понимаю. Исключение, которое бросается, ничего не указывает на мой код, но оно бросается только после того, как я повторно закрою TreeTableView, очистив дочерние элементы корневого элемента и добавив к нему новый набор och children.Исключение Javafx при нажатии TreeTableCell после repopulating TreeTableView

Это исключение:

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException 
at javafx.scene.control.TreeTableView$TreeTableViewArrayListSelectionModel.handleSelectedCellsListChangeEvent(TreeTableView.java:3056) 
at javafx.scene.control.TreeTableView$TreeTableViewArrayListSelectionModel.clearAndSelect(TreeTableView.java:2527) 
at com.sun.javafx.scene.control.behavior.TableCellBehaviorBase.simpleSelect(TableCellBehaviorBase.java:209) 
at com.sun.javafx.scene.control.behavior.TableCellBehaviorBase.doSelect(TableCellBehaviorBase.java:148) 
at com.sun.javafx.scene.control.behavior.CellBehaviorBase.mousePressed(CellBehaviorBase.java:132) 
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:95) 
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89) 
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218) 
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80) 
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) 
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) 
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.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
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:198) 
at javafx.scene.Scene$MouseHandler.process(Scene.java:3724) 
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3452) 
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1728) 
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2461) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:348) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:273) 
at java.security.AccessController.doPrivileged(Native Method) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:382) 
at com.sun.glass.ui.View.handleMouseEvent(View.java:553) 
at com.sun.glass.ui.View.notifyMouse(View.java:925) 
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) 
at com.sun.glass.ui.win.WinApplication.lambda$null$141(WinApplication.java:102) 
at com.sun.glass.ui.win.WinApplication$$Lambda$37/1798286609.run(Unknown Source) 
at java.lang.Thread.run(Thread.java:745) 

Небольшой MCVE (нажмите "-" для того, чтобы заселить табличного дерева, а затем отредактировать ячейку, чтобы получить исключение):

package test; 

import javafx.application.Application; 
import javafx.beans.value.ObservableValue; 
import javafx.event.EventHandler; 
import javafx.scene.Scene; 
import javafx.scene.control.TitledPane; 
import javafx.scene.control.TreeItem; 
import javafx.scene.control.TreeTableColumn; 
import javafx.scene.control.TreeTableColumn.CellDataFeatures; 
import javafx.scene.control.TreeTableColumn.CellEditEvent; 
import javafx.scene.control.TreeTableView; 
import javafx.scene.control.cell.TextFieldTreeTableCell; 
import javafx.scene.input.KeyCode; 
import javafx.scene.input.KeyEvent; 
import javafx.stage.Stage; 
import javafx.util.Callback; 

public class BillingTableTest extends Application { 

    private Stage stage; 
    private Scene scene; 
    private TitledPane pane; 

    private TreeTableView<String> table; 
    private TreeItem<String> root; 

    /** 
    * Start the program from scratch. 
    * 
    * @param args 
    *   Input arguments. Leave empty. 
    */ 
    public static void main(String[] args) { 
     launch(args); 
    } 

    /** 
    * Start the program. Not usually called by the user, but by JavaFX. Nothing 
    * fancy here, but setting up a basic TreeTableView with one column. 
    */ 
    public void start(Stage stage) { 
     this.stage = stage; 
     pane = new TitledPane(); 
     scene = new Scene(pane); 

     pane.setOnKeyReleased(new EventHandler<KeyEvent>() { 

      @Override 
      public void handle(KeyEvent event) { 
       // TODO Auto-generated method stub 
       if (event.getCode() == KeyCode.SUBTRACT) { 
        repopulate(); 
       } 
      } 
     }); 

     table = new TreeTableView<>(); 

     root = new TreeItem<>("Root"); 
     root.setExpanded(true); 

     table.setRoot(root); 
     table.setShowRoot(false); 
     table.setEditable(true); 

     TreeTableColumn<String, String> column = new TreeTableColumn<String, String>("String"); 

     column.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<String, String>, ObservableValue<String>>() { 
      @Override 
      public ObservableValue<String> call(CellDataFeatures<String, String> param) { 
       // TODO Auto-generated method stub 
       return param.getValue().valueProperty(); 
      } 
     }); 
     column.setCellFactory(TextFieldTreeTableCell.forTreeTableColumn()); 
     column.setOnEditCommit(new EventHandler<TreeTableColumn.CellEditEvent<String, String>>() { 
      @Override 
      public void handle(CellEditEvent<String, String> t) { 
       t.getTreeTablePosition().getTreeItem().setValue(t.getNewValue()); 
      } 
     }); 

     table.getColumns().add(column); 

     populate(); 

     pane.setContent(table); 

     stage.setScene(scene); 
     stage.show(); 

     System.out.println("TreeTableView has not been repopulated. Editing will not throw an exception."); 
     System.out.println("Press - to repopulate it and break it."); 
    } 

    /** 
    * Populate the TreeTableView with some dummy data. 
    */ 
    private void populate() { 
     for (int i = 1; i <= 10; i++) { 
      String string = "String " + i; 
      TreeItem<String> treeItem = new TreeItem<String>(string); 
      root.getChildren().add(treeItem); 
     } 
    } 

    /** 
    * Clear root children (clears the TreeTableView). Cell editing is most 
    * likely broken by this. 
    */ 
    private void clear() { 
     root.getChildren().clear(); // <- Most likely the problem. 
    } 

    /** 
    * Repopulate the root node (repopulate the TreeTableView). After this 
    * method is called, cell editing will throw an excetion. 
    */ 
    private void repopulate() { 
     clear(); // <- Most likely the problem. 
     populate(); 
     System.out.println("TreeTableView has been repopulated. Editing will now throw an exception"); 
    } 

} 

Я понимаю что ошибка связана с выбором TreeTableCells, и это происходит при выборе одного после первого повторного заполнения таблицы. В противном случае, перед повторным заселением, все работает так, как ожидалось, и никаких исключений не возникает.

В чем проблема? Вам не разрешено очищать дочерние элементы ObservableList в TreeTableRoow, иначе это должно быть сделано по-другому?

+0

Можете ли вы опубликовать [MCVE] (http://stackoverflow.com/help/mcve) –

+0

Я добавил очень маленький пример теперь @James_D. Нажмите «-», чтобы повторно заполнить TreeTableView. Редактирование ячеек работает до этого, но выбор ячейки после повторного заполнения будет вызывать исключение выше. –

+1

worksforme (заменил выражение на F1, хотя и не на моем рабочем столе) в 8u40b15. Исправлено множество ошибок с 8u20, может быть связано с одним из них? – kleopatra

ответ

1
private void populate() { 
    root.getChildren().clear() 
    for (int i = 1; i <= 10; i++) { 
     String string = "String " + i; 
     TreeItem<String> treeItem = new TreeItem<String>(string); 
     root.getChildren().add(treeItem); 

     // --------------Clear the selection ------------- 
     table.getSelectionModel().clearSelection(); 
     // ----------------------------------------------- 

    } 
} 
+0

Спасибо, что я искал этот ответ, отчаянно он работает, надеюсь, что это будет принято. – Wermerb