如何设置与选定行相邻的 TableView 行的样式?

Posted

技术标签:

【中文标题】如何设置与选定行相邻的 TableView 行的样式?【英文标题】:How can I style a TableView row adjacent to a selected row? 【发布时间】:2020-07-28 18:18:34 【问题描述】:

如何设置与当前选定行相邻的 TableView 行的样式?

我想这样做的原因是在选择行时更改行周围边框的颜色,包括顶部和底部。

我目前设置单元格边框(即表格的网格)的方式是在单元格底部设置一个 1px 的背景色。本质上,每个单元格都绘制自己的底部边框。

这意味着如果我想同时更改选定行的“顶部”和底部边框,我还需要能够设置当前选定单元格上方的单元格样式。

【问题讨论】:

【参考方案1】:

您可以为表格行的索引和表格的选定索引添加一个侦听器,这会更新表格行上的自定义 CSS 伪类:

TableView<MyTableType> table = ... ;
PseudoClass beforeSelected = PseudoClass.getPseudoClass("before-selected");

table.setRowFactory(tv -> 
    TableRow<MyTableType> row = new TableRow<>();
    ChangeListener<Number> listener = (obs, oldValue, newValue) -> 
        if (row.isEmpty()) 
            row.pseudoClassStateChanged(beforeSelected, false);
         else 
            row.pseudoClassStateChanged(beforeSelected, 
                row.getIndex() == table.getSelectionModel().getSelectedIndex() - 1);
        
    ;
    row.indexProperty().addListener(listener);
    table.getSelectionModel().selectedIndexProperty().addListener(listener);
    return row ;
);

然后在您的 CSS 文件中,您可以使用选择器设置所选行前面的表格行的样式

.table-row-cell:before-selected 
    /* styles here... */

这是一个完整的工作示例:

import java.util.function.Function;

import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.css.PseudoClass;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class StyleTest extends Application 

    @Override
    public void start(Stage stage) throws Exception 
        TableView<Item> table = new TableView<>();
        PseudoClass beforeSelected = PseudoClass.getPseudoClass("before-selected");
        table.setRowFactory(tv -> 
            TableRow<Item> row = new TableRow<>();
            ChangeListener<Number> listener = (obs, oldValue, newValue) -> 
                if (row.isEmpty()) 
                    row.pseudoClassStateChanged(beforeSelected, false);
                 else 
                    row.pseudoClassStateChanged(beforeSelected, 
                            row.getIndex() == table.getSelectionModel().getSelectedIndex() - 1);
                
            ;
            row.indexProperty().addListener(listener);
            table.getSelectionModel().selectedIndexProperty().addListener(listener);
            return row ;
        );
        
        table.getColumns().add(column("Item", Item::nameProperty));
        table.getColumns().add(column("Value", Item::valueProperty));
                
        for (int i=1 ; i <= 100 ; i++) 
            table.getItems().add(new Item("Item "+i, i));
        
        
        Scene scene = new Scene(new BorderPane(table));
        scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
        stage.setScene(scene);
                
        stage.show();
        
        
    
    
    private static <S,T> TableColumn<S,T> column(String title, Function<S, Property<T>> prop) 
        TableColumn<S,T> column = new TableColumn<>(title);
        column.setCellValueFactory(cellData -> prop.apply(cellData.getValue()));
        return column ;
    

    
    public static class Item 
        private final StringProperty name = new SimpleStringProperty();
        private final IntegerProperty value = new SimpleIntegerProperty();
        
        public Item(String name, int value) 
            setName(name);
            setValue(value);
        

        public final StringProperty nameProperty() 
            return this.name;
        
        

        public final String getName() 
            return this.nameProperty().get();
        
        

        public final void setName(final String name) 
            this.nameProperty().set(name);
        
        

        public final IntegerProperty valueProperty() 
            return this.value;
        
        

        public final int getValue() 
            return this.valueProperty().get();
        
        

        public final void setValue(final int value) 
            this.valueProperty().set(value);
        
        
        
        
    
    
    public static void main(String[] args) 
        Application.launch(args);
    


还有一个例子style.css(它只是将前一行染成绿色...):

.table-row-cell:before-selected 
  -fx-background: #00b140 ;

【讨论】:

以上是关于如何设置与选定行相邻的 TableView 行的样式?的主要内容,如果未能解决你的问题,请参考以下文章

QML Tableview显示选定行的值

iPhone SDK如何将tableview中plist中的选定行传递到UIViewController

删除选定行的对象

Qt C++ 从 QTableView 中获取选定行的每个单元格的数据

显示带有选定行的 UIPickerView

如何获取列表视图选定行的小部件ID