JavaFx:如何在TableView中使用CSS进行持久选择

ztmd8pv5  于 2022-11-26  发布在  Java
关注(0)|答案(1)|浏览(180)

更新:插入项目(可复制示例)和最后详细信息
我有一个应用程序,它显示一个填充了简单对象(可观察列表)的TableView
我想在TableView中突出显示选定的项目(行)。
例如:如果用户按下'Insert',我将更新(在可观察列表中)所选的对象。对象中的布尔值将起作用。对象被“标记”;用户可以做其他事情。
我不能使用myTableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);,因为一旦按下键或点击鼠标,用户就会失去选择。
考虑到这一点,这意味着我这样管理键盘:

public boolean implementListenerPackage(Scene s) {
          //some init then...
          s.setOnKeyReleased(new EventHandler<KeyEvent>() {
                @Override
                public void handle(KeyEvent ke) {
                    switch (ke.getCode()) {
                        case INSERT:
                            setObservableListObjectSelect();
                            break;
                   }
               }
        });
    }

可观察列表中的对象相当简单:

public class myObject {
    private boolean selected;
    private String otherStuff = "";
// Then constructor , getters and setters

我还使用MouseEvent管理来处理其他操作。在创建TableView时,我添加了以下内容:

myTableView.setRowFactory(rftv-> {
                    TableRow<type> rowObj = new TableRow<>();
                    rowObj.setOnMousePressed(new EventHandler<MouseEvent>() {
                        @Override
                        public void handle(MouseEvent e) {
                           if (e.getClickCount() == 2 && (!rowObj.isEmpty())) {
                                SomeClass.doSomethingForDoubleClik()
                            } else { // Simple clic
                                SomeClass.doSomethingForSimpleClik()
                            }
                        }
                    });
                    return rowObj;
                });

我的目标是在myObject布尔值改变时改变行的CSS,这样做可以使用户选择高亮显示,即使用户点击了另一行。
我试探着:

  • 在这个网站上读了很多书,但都是为了找到简单的例子。而不是我同时遇到几个障碍的那个。
  • 在rowFactory中实现更多的东西。但是我不能这样做。如果它编译了,那么它会崩溃并出现一个空指针异常。我从来不擅长那些复杂的语法。
  • 我想直接从键盘管理来做,但发现它相当复杂。我必须得到选定的对象,更新它,然后找到选定的单元格,并逐个更改CSS(列逻辑)。
  • 以实现对象和行之间的“绑定”(An example here),但却发现自己不知道如何实现它,因为它是另一个问题“味道”的答案。

它可能就在我眼前,但我看不到它。
更新:请记住

  • 键盘管理是集中式的。
  • tableView上已存在出厂设置。
  • 它们是原始应用程序中的几个TableView,所以我希望CSS样式会自动更改,而不是以某种“硬编码”的方式。

最小代码:
第一个

kiz8lqtg

kiz8lqtg1#

找到了!
简单又复杂。
技巧是在对象属性的正确位置插入一个侦听器。

  • 在行工厂定义内。
  • 在@override之前
  • 将行对象作为参数传递,然后“瞧”。

类似于:

rowObj.itemProperty().addListener((observable, oldValue, newValue) -> updateTableRowCss(rowObj, newValue));

备注:

  • 可以在不同的对象属性上添加多个侦听器。
  • 我强烈建议你创建一个监听器将调用的方法。有时IDE语法分析器会在屏幕上制造混乱。它无助于在这种类型的代码中找到错误。
  • 从我所做的测试来看,你对样式所做的修改似乎会在已经加载的样式上进行(更重要的是)。

通过这种方式,您可以在工厂中保持集中的键盘管理(如本例中所示)和鼠标事件管理。
光标仍然可以自由移动,并且可以保留一个对象选择,以便以后重复使用。
上面修改过的示例代码:

package application;
    
    import javafx.application.Application;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.event.EventHandler;
    import javafx.stage.Stage;
    import javafx.scene.Scene;
    import javafx.scene.control.Label;
    import javafx.scene.control.TableColumn;
    import javafx.scene.control.TableRow;
    import javafx.scene.control.TableView;
    import javafx.scene.control.cell.PropertyValueFactory;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.layout.VBox;
    
    public class Main extends Application {
    
        Label lbl01 = new Label("Information");
    
        @Override
        public void start(Stage primaryStage) {
            try {
                TableView tv1 = new TableView();
                TableColumn<MyObject, String> column1 = new TableColumn<>("Col 01");
                column1.setCellValueFactory(new PropertyValueFactory<>("keyboardSelected"));
    
                TableColumn<MyObject, String> column2 = new TableColumn<>("Col 02");
                column2.setCellValueFactory(new PropertyValueFactory<>("dataA"));
    
                TableColumn<MyObject, String> column3 = new TableColumn<>("Col 03");
                column3.setCellValueFactory(new PropertyValueFactory<>("dataB"));
    
                TableColumn<MyObject, String> column4 = new TableColumn<>("Col 04");
                column4.setCellValueFactory(new PropertyValueFactory<>("dataC"));
    
                tv1.getColumns().add(column1);
                tv1.getColumns().add(column2);
                tv1.getColumns().add(column3);
                tv1.getColumns().add(column4);
    
                ObservableList<MyObject> olm1 = FXCollections.observableArrayList();
                olm1.addAll(new MyObject(false, "Object01 A", "Object01 B", "Object01 C"),
                        new MyObject(false, "Object02 A", "Object02 B", "Object02 C"),
                        new MyObject(false, "Object03 A", "Object03 B", "Object03 C"),
                        new MyObject(false, "Object04 A", "Object04 B", "Object04 C"),
                        new MyObject(false, "Object05 A", "Object05 B", "Object05 C")
                        );
    
                tv1.setItems(olm1);
    
                tv1.setRowFactory(dc -> {
                    TableRow<MyObject> rowObj = new TableRow<>();
                    rowObj.itemProperty().addListener((observable, oldValue, newValue) -> updateTableRowCss(rowObj, newValue));
                    rowObj.setOnMousePressed(new EventHandler<MouseEvent>() {
                        @Override
                        public void handle(MouseEvent e) {
                            if (e.getClickCount() == 2 && (!rowObj.isEmpty())) {
                                lbl01.setText("Double click on line " + tv1.getSelectionModel().getSelectedIndex());
    
                            } else {
                                lbl01.setText("Single click on line " + +tv1.getSelectionModel().getSelectedIndex());
                            }
                        }
                    });
                    return rowObj;
                });
    
                VBox root = new VBox(tv1, lbl01);
                Scene scene = new Scene(root, 512, 640);
                primaryStage.setScene(scene);
    
                KeyboardManagement km = new KeyboardManagement();
                km.implementListener(scene, lbl01, tv1);
    
                primaryStage.show();
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    
        
        private void updateTableRowCss(TableRow<MyObject> rowObj, MyObject item) {
            // On doit vérifier si null
            if (item != null ) {
                if (item.isKeyboardSelected()) {
                    rowObj.setStyle("-fx-background-color: #FF000080;");
                } else {
                    rowObj.setStyle("");
                }
            }
        }
        
        
    }

Final result

相关问题