【问题标题】:Javafx Listview Add and edit elementJavafx Listview 添加和编辑元素
【发布时间】:2015-12-18 10:27:13
【问题描述】:

我想直接向列表视图添加和编辑元素:

/*
 * 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);
    }

}

一切似乎都正确但不起作用,它喜欢尝试修改第一个项目而不是最后一个索引中新添加的项目,我不知道为什么

【问题讨论】:

    标签: java user-interface javafx


    【解决方案1】:

    这是一个错误。

    焦点和编辑之间似乎存在一些真正可怕的相互作用。基本问题似乎是,当列表单元格失去焦点时,它会取消任何编辑。我认为通过单击按钮,您会导致焦点转移到该按钮,然后在下一个渲染脉冲上,列表单元格会看到它失去焦点并取消编辑。我不能完全解释为什么列表中的第一个项目似乎进入了编辑状态,但我怀疑这是由于与列表的 focusModel 进行了进一步的交互,它管理单个项目的焦点。

    对于真正丑陋的 hack,使用 AnimationTimer 将调用 ListView.edit(...) 延迟一个额外的渲染帧。 (如果您不熟悉它,AnimationTimer 定义了一个 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();
        });
    

    使用索引而不是项目调用 scrollTo(...) 似乎也更健壮(尤其是当你有彼此相等的项目时:)。

    也许其他人可以想出一些更清洁的东西...

    【讨论】:

    • 这个错误已经报告给 javafx 的开发者了??
    • 自从他们搬家后我就没有检查过错误报告,但我在那里看不到任何类似的东西。你可能应该report it
    • 我猜问题是ListCells 在调用edit 之前没有更新。至少调用layout() 似乎可以解决问题,请参阅my answer below。似乎比使用AnimationTimer 等待下一个布局脉冲要好...
    【解决方案2】:

    问题似乎是在调用edit 之前没有更新Cells。由于更新单元格是在布局期间完成的,因此在开始编辑之前调用 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();
    }
    

    【讨论】:

      【解决方案3】:

      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);
          }
      }
      

      【讨论】:

      • 不工作,还有很多无效的编辑位置
      • 这个例子只是为了演示编辑索引的行为。它不打算成为一种解决方法。我认为这个错误尚未报告,但我没有在bugs.openjdk.java.net进行深入搜索
      猜你喜欢
      • 1970-01-01
      • 2016-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多