2017-09-05 15 views
1

ユーザにとって使いやすいjavaFXで編集可能なリストビューを作成しようとしています。これを行うには、on editコミット機能を使用しました。私はそれが欲しいと思っていたことを全般的にうまくやっていましたが、1つの問題に遭遇しました。ユーザーが最後のアイテムを編集するたびに、別のアイテムを作成して編集を開始したいと思います。これは些細なものですが、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による再編集がキャンセルされることです。キャンセルを引き起こすことができる多くの(そして複雑な)パスがありますが、そのうちの1つは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

関連する問題