当鼠标悬停在列上时,JavaFX如何突出显示TableColumn而不是TableRow [英] JavaFX how to highlight TableColumn instead of TableRow when mouse is hovered to column

查看:131
本文介绍了当鼠标悬停在列上时,JavaFX如何突出显示TableColumn而不是TableRow的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找到一种解决方案,当鼠标位于该列顶部时,突出显示表列,但是我找不到解决方案.有人已经找到解决方案了吗?我已经尝试过使用ScenicView来查看CSS和组件,但这并没有太大帮助.

I have tried to find a solution to highlight table column when mouse is on top of that column, but I have not been able to find a solution. Is someone already found some solution for that? I have already tried to take a look to css and components with ScenicView, but it is not helping very much.

推荐答案

如果您使用的是Java 8,则可以使用CSS伪类很好地做到这一点. CSS伪类的性能非常好(至少,顺便说一下,这是更改JavaFX控件样式的最快方法),并且由于表视图仅会创建少量表单元格,即使对于非常大的数据集也是如此.应该表现很好.

If you're using Java 8, you can do this quite nicely using a CSS pseudoclass. The performance of CSS pseudoclasses is very good (anecdotally, at least, it is the fastest way to change the style of JavaFX controls), and since the table view only creates a small number of table cells, even for very large data sets, this should perform very well.

定义一个外部CSS类,该类使用自定义伪类来设置表单元格的样式,如下所示:

Define an external css class that sets the style of a table cell with a custom pseudoclass applied as follows:

.table-cell:column-hover {
    -fx-background-color: -fx-cell-focus-inner-border, -fx-selection-bar  ;
    -fx-background-insets: 0, 0 0 1 0 ;
    -fx-background: -fx-selection-bar ;
}

(这里的-fx-background-color实际上会改变背景颜色:-fx-background只是一个技巧,可确保文本填充相对于背景保持合适的颜色.)

(The -fx-background-color here actually changes the background color: the -fx-background is just a trick to ensure the text fill stays a suitable color relative to the background.)

现在,为每列定义一个布尔属性.为每列创建一个单元格工厂,当鼠标移到一个单元格上时将boolean属性设置为true,而当鼠标移开时将其设置为false.让每个单元格观察其boolean属性,并在单元格更改时设置其伪类状态.

Now, for each column, define a boolean property. Create a cell factory for each column that sets the boolean property to true when the mouse moves over a cell, and sets it to false when the mouse moves off. Have each cell observe the boolean property and set the pseudoclass state for the cell when it changes.

这是一个示例,使用来自Person表"rel =" nofollow>标准教程.有趣的代码在createCol(...)方法中:

Here's an example, using the usual Person table from the standard tutorial. The interesting code is in the createCol(...) method:

import java.util.function.Function;

import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.css.PseudoClass;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class TableViewTest extends Application {

    private static final PseudoClass COLUMN_HOVER_PSEUDO_CLASS = PseudoClass.getPseudoClass("column-hover");

    @Override
    public void start(Stage primaryStage) {
        TableView<Person> table = new TableView<>();
        TableColumn<Person, String> firstNameCol = createCol("First Name", Person::firstNameProperty, 150);
        TableColumn<Person, String> lastNameCol = createCol("Last Name", Person::lastNameProperty, 150);
        TableColumn<Person, String> emailCol = createCol("Email", Person::emailProperty, 200);

        table.getItems().addAll(
            new Person("Jacob", "Smith", "jacob.smith@example.com"),
            new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
            new Person("Ethan", "Williams", "ethan.williams@example.com"),
            new Person("Emma", "Jones", "emma.jones@example.com"),
            new Person("Michael", "Brown", "michael.brown@example.com")
        );

        table.getColumns().add(firstNameCol);
        table.getColumns().add(lastNameCol);
        table.getColumns().add(emailCol);

        VBox root = new VBox(15, table);
        root.setAlignment(Pos.CENTER);
        Scene scene = new Scene(root, 800, 600);

        scene.getStylesheets().add("table-column-hover.css");

        primaryStage.setScene(scene);
        primaryStage.show();
    }


    private TableColumn<Person, String> createCol(String title, 
            Function<Person, ObservableValue<String>> mapper, double size) {

        TableColumn<Person, String> col = new TableColumn<>(title);

        col.setCellValueFactory(cellData -> mapper.apply(cellData.getValue()));

        // Is the column being hovered over with the mouse?
        BooleanProperty columnHover = new SimpleBooleanProperty();

        col.setCellFactory(column -> {

            // basic table cell:
            TableCell<Person, String> cell = new TableCell<Person, String>() ;
            cell.textProperty().bind(cell.itemProperty());

            // when the mouse hovers over the cell, set the columnHover to indicate 
            // the mouse is over the column:
            cell.hoverProperty().addListener((obs, wasHovered, isNowHovered) -> {
                columnHover.set(isNowHovered);
            });

            // update the column-hover pseudoclass state for this cell when the column is hovered over
            // note this will activate the pseudoclass when the mouse is over any cell in this column
            columnHover.addListener((obs, columnWasHovered, columnIsNowHovered) -> 
                cell.pseudoClassStateChanged(COLUMN_HOVER_PSEUDO_CLASS, columnIsNowHovered)
            );

            return cell ;
        });

        col.setPrefWidth(size);

        return col ;
    }

    public class Person {
        private final StringProperty firstName = new SimpleStringProperty(this, "firstName");
        private final StringProperty lastName = new SimpleStringProperty(this, "lastName");
        private final StringProperty email = new SimpleStringProperty(this, "email");

        public Person(String firstName, String lastName, String email) {
            this.firstName.set(firstName);
            this.lastName.set(lastName);
            this.email.set(email);
        }

        public final StringProperty firstNameProperty() {
            return this.firstName;
        }

        public final java.lang.String getFirstName() {
            return this.firstNameProperty().get();
        }

        public final void setFirstName(final java.lang.String firstName) {
            this.firstNameProperty().set(firstName);
        }

        public final StringProperty lastNameProperty() {
            return this.lastName;
        }

        public final java.lang.String getLastName() {
            return this.lastNameProperty().get();
        }

        public final void setLastName(final java.lang.String lastName) {
            this.lastNameProperty().set(lastName);
        }

        public final StringProperty emailProperty() {
            return this.email;
        }

        public final java.lang.String getEmail() {
            return this.emailProperty().get();
        }

        public final void setEmail(final java.lang.String email) {
            this.emailProperty().set(email);
        }

    }

    public static void main(String[] args) {
        launch(args);
    }
}

这篇关于当鼠标悬停在列上时,JavaFX如何突出显示TableColumn而不是TableRow的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆