要素をリストビューに直接追加して編集したい:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package javafx_test;
import Java.util.Observable;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.cell.TextFieldListCell;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.StringConverter;
/**
*
* @author karim
*/
public class Javafx_test extends Application {
@Override
public void start(Stage primaryStage) {
ObservableList<String> items = FXCollections.observableArrayList("test1", "test2");
ListView<String> list = new ListView<>(items);
list.setEditable(true);
list.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
@Override
public ListCell<String> call(ListView<String> param) {
return new TextFieldListCell<>(new StringConverter<String>() {
@Override
public String toString(String object) {
return object;
}
@Override
public String fromString(String string) {
return string;
}
});
}
});
Button btn = new Button();
btn.setText("Add String");
btn.setOnAction((ActionEvent event) -> {
String c = new String("test");
list.getItems().add(list.getItems().size(), c);
list.scrollTo(c);
list.edit(list.getItems().size() - 1);
});
VBox root = new VBox(list, btn);
Scene scene = new Scene(root);
primaryStage.setTitle("test!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
すべてが正しいように見えますが、機能していません。最後のインデックスに新しく追加されたアイテムではなく、最初のアイテムを変更しようとしているようです。理由はわかりません。
それはバグです。
フォーカスと編集の間に本当に恐ろしい相互作用があるようです。基本的な問題は、リストのセルがフォーカスを失うと、編集をキャンセルすることです。ボタンをクリックするとフォーカスがそのボタンに移動し、次のレンダリングPulseでリストセルがフォーカスを失ったことを確認して編集をキャンセルすると思います。リストの最初のアイテムが編集状態になっているように見える理由を完全に説明することはできませんが、個々のアイテムのフォーカスを管理するリストのfocusModel
とのさらなる相互作用が原因であると思います。
本当に醜いハックの場合、AnimationTimer
を使用して、追加のレンダリングフレームによるListView.edit(...)
の呼び出しを遅らせます。 (慣れていない場合は、 AnimationTimer
が、レンダリングパルスごとに1回呼び出されるhandle(...)
メソッドを定義します。ここでは、1フレームだけカウントします次に、editを呼び出して、タイマーを停止します。)
_ btn.setOnAction((ActionEvent event) -> {
String c = "test"+(list.getItems().size()+1);
list.getItems().add(list.getItems().size(), c);
list.scrollTo(list.getItems().size() - 1);
// list.edit(list.getItems().size() - 1);
new AnimationTimer() {
int frameCount = 0 ;
@Override
public void handle(long now) {
frameCount++ ;
if (frameCount > 1) {
list.edit(list.getItems().size() - 1);
stop();
}
}
}.start();
});
_
項目の代わりにインデックスを使用してscrollTo(...)
を呼び出すと、より堅牢に見えます(特に、互いに等しい項目があるためです:)。
多分他の誰かがこれよりも少しきれいなものを思いつくことができます...
問題は、Cell
を呼び出す前にedit
sが更新されていないことです。セルの更新はレイアウト中に行われるため、編集を開始する前にlayout
を呼び出すと問題が解決します。
例:
@Override
public void start(Stage primaryStage) {
ListView<String> listView = new ListView<>();
listView.setEditable(true);
listView.setCellFactory(TextFieldListCell.forListView());
Button editButton = new Button("Add & Edit");
editButton.setOnAction((ActionEvent event) -> {
listView.getItems().add("");
listView.scrollTo(listView.getItems().size() - 1);
listView.layout();
listView.edit(listView.getItems().size() - 1);
});
Scene scene = new Scene(new VBox(listView, editButton));
primaryStage.setScene(scene);
primaryStage.show();
}
James_Dがすでに述べたこと:editメソッドのインデックスが正しく計算されていないようです。次の例では、正しいインデックスを取得しない必要がありますが、取得します。
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.cell.TextFieldListCell;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ListEdit extends Application {
int i = 3;
@Override
public void start(Stage primaryStage) {
ObservableList<String> items = FXCollections.observableArrayList("test1", "test2");
ListView<String> list = new ListView<>(items);
list.setCellFactory(TextFieldListCell.forListView());
list.setEditable(true);
Button btn = new Button();
btn.setText("Add String");
btn.setOnAction((ActionEvent event) -> {
list.getItems().add(i - 1, "test" + i);
list.edit(i - 2);
i++;
});
VBox root = new VBox(list, btn);
Scene scene = new Scene(root);
primaryStage.setTitle("test!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}