Javafx Listview 添加和编辑元素
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32700005/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Javafx Listview Add and edit element
提问by karim
i want to add and edit directly an element to a listview :
我想直接向列表视图添加和编辑元素:
/*
* 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);
}
}
Everything seems correct but that not working, it like its try to modify the first item not the newly added item in the last index, i don't know why
一切似乎都正确但不起作用,就像它尝试修改第一个项目而不是最后一个索引中新添加的项目一样,我不知道为什么
采纳答案by James_D
That's a bug.
那是一个错误。
There seems to be some truly horrible interplay between focus and editing. The basic problem seems to be that when a list cell loses focus, it cancels any editing. I think that by clicking on the button, you cause the focus to shift to that button, and then on the next rendering pulse the list cell sees it has lost focus and cancels editing. I can't quite explain why the first item in the list appears to go to an editing state, but I suspect it is due to some further interaction with the list's focusModel
, which manages focus of individual items.
焦点和编辑之间似乎有一些真正可怕的相互作用。基本问题似乎是当列表单元格失去焦点时,它会取消任何编辑。我认为通过单击按钮,您会导致焦点转移到该按钮上,然后在下一个渲染脉冲中,列表单元格看到它已失去焦点并取消编辑。我不能完全解释为什么列表中的第一个项目似乎进入编辑状态,但我怀疑这是由于与列表的 进行了一些进一步的交互focusModel
,它管理单个项目的焦点。
For a truly ugly hack, use an AnimationTimer
to delay the call to ListView.edit(...)
by an additional rendering frame. (In case you're not familiar with it, an AnimationTimer
defines a handle(...)
method that is invoked once on each rendering pulse; here I just count one frame and then call edit, and stop the timer.)
对于真正丑陋的 hack,请使用 anAnimationTimer
来延迟对ListView.edit(...)
附加渲染帧的调用。(如果您不熟悉它,anAnimationTimer
定义了一个handle(...)
在每个渲染脉冲上调用一次的方法;这里我只计算一帧,然后调用编辑,并停止计时器。)
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();
});
Calling scrollTo(...)
with an index instead of an item seems more robust too (especially as you have items in there that are equal to each other :).)
scrollTo(...)
使用索引而不是项目进行调用似乎也更健壮(尤其是当您有彼此相等的项目时:)。
Maybe someone else can come up with something a bit cleaner that this...
也许其他人可以想出一些更清洁的东西,这...
回答by aw-think
What James_D already mentioned: It seems that the index for the edit method is calculated wrong. In the following example it should notgrab the correct index, but it does.
James_D 已经提到的: 似乎编辑方法的索引计算错误。在下面的例子中,应该没有抓住正确的索引,但它确实。
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);
}
}
回答by fabian
The issue seems to be the Cell
s not being updated before calling edit
. Since updating the cells is done during layout, calling layout
before starting the edit should fix the issue:
问题似乎是Cell
在调用 s 之前没有更新edit
。由于更新单元格是在布局期间完成的,因此layout
在开始编辑之前调用应该可以解决问题:
Example:
例子:
@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();
}