2017-09-05 75 views
1

我正嘗試在javaFX中創建易於用戶使用的可編輯列表視圖。爲此,我使用了on編輯提交功能。我一般很擅長做我想做的事情,但是我遇到了一個問題。每次用戶編輯最後一個項目時,我都希望它創建另一個項目並開始編輯該項目。看起來好像這是微不足道的,但是我遇到了在setOnEditCommit函數中運行dit函數的問題。這裏是我的代碼:JavaFX:在onEditCommit函數中使用ListView.edit(int itemIndex)

personList.setOnEditCommit(new EventHandler<ListView.EditEvent<String>>() { 
     @Override 
     public void handle(ListView.EditEvent<String> t) { 
      personList.getItems().set(t.getIndex(), t.getNewValue()); 

      if(personList.getSelectionModel().getSelectedIndices().contains(personList.getItems().size()-1)) { 
       int personNumber = personList.getItems().size() + 1; 
       personList.getItems().add("person " + personNumber); 
       personList.edit(personList.getItems().size()-1); //the line that is not working. 
      } 
     } 

    }); 

注:personlist是一個ListView

有反正從與中集上setOnEditCommit運行編輯功能。謝謝。

+0

看起來像一個錯誤對我說:事件序列是怪異 - 那一刻,你通過設置新項目修改數據(FI),有一箇中間cancelEvent ...編輯虛擬控件是真的,真的被打破... – kleopatra

+0

原因可能是「修復」https://bugs.openjdk.java.net/browse/JDK-8094887 - 編輯取消任何更改基礎數據 – kleopatra

回答

1

基本問題是由commitHandler重新編輯被取消。有許多(錯綜複雜的)路徑可以觸發取消,其中一個似乎是對「JDK-8094887」的「修復」,它會粗暴地取消對數據更改的任何編輯。

但由於取消了重新編輯的單元配置過程中觸發後,大約收到了不能原委:

indexedCell.updateIndex(index) 
-> listCell.indexChanged(oldIndex, newIndex) 
-> listCell.updateFocus() 
-> node.setFocused(xx) //for some reason xx is false 
-> cell.focusedListener 
-> cancelEdit() 

運行下面的例子中,編輯單個項目,按ENTER鍵產生輸出:

edit start: 0 // start edit on last row 
edit commit: 0 // commit the edit by items.set(...) 
edit cancel: -1 // cancel triggered by modification 
edit start: 1 // re-edit the added item 
edit cancel: -1 // cancel triggered by cell config 

唯一的出路,我可以拿出很脆:開始重新編輯爲你做什麼,然後又開始說,「等待」,直到所有的內部配置做了計時器,然後再次編輯。沒有什麼,我們希望在生產代碼做,很明顯;)

import javafx.animation.KeyFrame; 
import javafx.animation.Timeline; 
import javafx.application.Application; 
import javafx.collections.FXCollections; 
import javafx.scene.Scene; 
import javafx.scene.control.ListView; 
import javafx.scene.control.cell.TextFieldListCell; 
import javafx.scene.layout.BorderPane; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

/** 
* Trying to add item/start edit on new item in commitHandler: 
* https://stackoverflow.com/q/46047134/203657 
* 
* one last try: use timer to start editing some time later .. 
*/ 
public class ListViewAutoEditInHandler extends Application { 

    private ListView<String> simpleList; 
    private int expectedEditIndex = -1; 
    private Timeline editTimer; 

    /** 
    * Callback for editTimer. Implemented to scroll to and force 
    * edit of cell at expectedEditIndex. 
    */ 
    private void checkEdit() { 
     if (expectedEditIndex < 0) return; 
     if (expectedEditIndex == simpleList.getEditingIndex()) { 
      expectedEditIndex = -1; 
      return; 
     } 
     int index = expectedEditIndex; 
     expectedEditIndex = -1; 
     simpleList.scrollTo(index); 
     simpleList.edit(index); 
    } 

    @Override 
    public void start(Stage primaryStage) { 
     editTimer = new Timeline(new KeyFrame(Duration.millis(100), ae -> checkEdit())); 
     simpleList = new ListView<>(FXCollections.observableArrayList("Item1")); 
     simpleList.setEditable(true); 

     simpleList.setCellFactory(TextFieldListCell.forListView()); 

     simpleList.setOnEditStart(t -> p("edit start: " + t.getIndex())); 
     simpleList.setOnEditCancel(t -> p("edit cancel: " + t.getIndex())); 
     simpleList.setOnEditCommit(t -> { 
      p("edit commit: " + t.getIndex()); 
      // any modification of the items will trigger a cancel 
      simpleList.getItems().set(t.getIndex(), t.getNewValue()); 
      // p("editing? " + simpleList.getEditingIndex()); 
      if (t.getIndex() == simpleList.getItems().size() - 1) { 
       expectedEditIndex = t.getIndex() + 1; 
       simpleList.getItems().add("newItem"); 
       simpleList.getSelectionModel().select(expectedEditIndex); 
       simpleList.edit(expectedEditIndex); 
       // ... so we start a timer to force 
       // uncomment for a brittle solution ;) 
       // editTimer.playFromStart(); 
      } else { 
       // reset .. a bit paranoid here ;) 
       expectedEditIndex = -1; 
       editTimer.stop(); 
      } 

     }); 


     BorderPane root = new BorderPane(simpleList); 
     Scene scene = new Scene(root, 300, 250); 

     primaryStage.setTitle("Hello World!"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    private static void p(String t) { 
     System.out.println(t); 
    } 
    public static void main(String[] args) { 
     launch(args); 
    } 
} 
+0

謝謝,我在生產中這樣做,所以......這是一個應該發生的錯誤還是可以報告的事情? – joshLor

+0

這就是問題;)在提交後接收取消顯然是一個錯誤,我認爲(與默認處理程序一樣,報告爲https://bugs.openjdk.java.net/browse/JDK-8187307)至於啓動在commitHandler中進行另一次編輯。我不太確定:在能夠可靠地啓動另一個循環之前,系統可能需要完成從編輯到未編輯的狀態轉換。另一方面:要求很簡單,我看不出如何/在哪裏實施它。 – kleopatra

相關問題