以编程方式更改TableView行外观 [英] Programmatically change the TableView row appearance

查看:149
本文介绍了以编程方式更改TableView行外观的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于TableView的Oracle教程之后,我想知道是否有一种方法可以以编程方式将不同的CSS样式应用于所选的TableView行。例如,用户选择某一行,单击突出显示按钮,所选行获得棕色背景,白色文本填充等。我已阅读 JavaFX tableview颜色更新TableView行外观 JavaFX中有两种颜色的背景?,但是没有avail = /

After doing a Oracle tutorial about the TableView, I was wondering if there's a way to programmatically apply different CSS style to the selected TableView row. For example, user selects a certain row, clicks the "Highlight" button and the selected row gets brown background, white text fill, etc. I've read the JavaFX tableview colors, Updating TableView row appearance and Background with 2 colors in JavaFX?, but to no avail =/

以下是来源:

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;

public class TableViewSample extends Application {

    private TableView<Person> table = new TableView<Person>();
    private final ObservableList<Person> data =
        FXCollections.observableArrayList(
            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")
        );

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

    @Override
    public void start(Stage stage) {
        Scene scene = new Scene(new Group());
        stage.setTitle("Table View Sample");
        stage.setWidth(450);
        stage.setHeight(600);

        final Label label = new Label("Address Book");
        label.setFont(new Font("Arial", 20));

        TableColumn firstNameCol = new TableColumn("First Name");
        firstNameCol.setMinWidth(100);
        firstNameCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("firstName"));

        TableColumn lastNameCol = new TableColumn("Last Name");
        lastNameCol.setMinWidth(100);
        lastNameCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("lastName"));

        TableColumn emailCol = new TableColumn("Email");
        emailCol.setMinWidth(200);
        emailCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("email"));

        table.setItems(data);
        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);

        final Button btnHighlight = new Button("Highlight selected row");
        btnHighlight.setMaxWidth(Double.MAX_VALUE);
        btnHighlight.setPrefHeight(30);

        btnHighlight.setOnAction(new EventHandler<ActionEvent>(){
            public void handle(ActionEvent e){
                // this is where the CSS should be applied
            }
        });

        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.setPadding(new Insets(10, 0, 0, 10));
        vbox.getChildren().addAll(label, table, btnHighlight);

        ((Group) scene.getRoot()).getChildren().addAll(vbox);

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

    public static class Person {

        private final SimpleStringProperty firstName;
        private final SimpleStringProperty lastName;
        private final SimpleStringProperty email;

        private Person(String fName, String lName, String email) {
            this.firstName = new SimpleStringProperty(fName);
            this.lastName = new SimpleStringProperty(lName);
            this.email = new SimpleStringProperty(email);
        }

        public String getFirstName() {
            return firstName.get();
        }

        public void setFirstName(String fName) {
            firstName.set(fName);
        }

        public String getLastName() {
            return lastName.get();
        }

        public void setLastName(String fName) {
            lastName.set(fName);
        }

        public String getEmail() {
            return email.get();
        }

        public void setEmail(String fName) {
            email.set(fName);
        }
    }
} 

应用程序.css 突出显示所选行按钮将highlightRow类应用于所选表格行:

And the application.css from which the "Highlight selected row" button applies the highlightedRow class to the selected table row:

.highlightedRow {
    -fx-background-color: brown;
    -fx-background-insets: 0, 1, 2;
    -fx-background: -fx-accent;
    -fx-text-fill: -fx-selection-bar-text;
}



编辑:



经过几个小时的尝试,我能想到的最好的事情是这个使用以下代码:

firstNameCol.setCellFactory(new Callback<TableColumn<Person, String>, TableCell<Person, String>>() {
    @Override
    public TableCell<Person, String> call(TableColumn<Person, String> personStringTableColumn) {
        return new TableCell<Person, String>() {
            @Override
            protected void updateItem(String name, boolean empty) {
                super.updateItem(name, empty);
                if (!empty) {
                    if (name.toLowerCase().startsWith("e") || name.toLowerCase().startsWith("i")) {
                        getStyleClass().add("highlightedRow");
                    }
                    setText(name);
                } else {
                    setText("empty");  // for debugging purposes
                }
            }
        };
    }
});

我不太明白的部分是为什么我不能从<$里面那样做c $ c> setOnAction btnHighlight 的方法?之后我也尝试刷新表格(此处描述),但它似乎没有用。此外,我的解决方案仅适用于 firstNameCol 列,因此必须为每列设置新的单元格工厂才能应用某种样式,或者是否存在更聪明的解决方案?

The part I don't really understand is why I can't do that from inside the setOnAction method of the btnHighlight? I also tried refreshing the table afterwards (described here), but it didn't seem to work. Also, my "solution" only works for the firstNameCol column, so does one have to set new cell factory for each column in order to apply a certain style, or is there a smarter solution?

推荐答案

如果你不想要我上面发布的解决方案的可重用性,这实际上是一样的但是对行工厂使用匿名内部类而不是独立类。也许代码更易于遵循,因为它们都集中在一个地方。这是Jonathan的解决方案和我的解决方案之间的混合体,但会自动更新亮点而不会强制它。

If you don't want the reusability of the solution I posted above, this is really the same thing but using an anonymous inner class for the row factory instead of a standalone class. Perhaps the code is easier to follow as it's all in one place. It's kind of a hybrid between Jonathan's solution and mine, but will automatically update the highlights without forcing it with a sort.

我使用了一个整数列表,因此它支持多项选择,但如果你不需要,你可以显然只使用IntegerProperty。

I used a list of integers so it supports multiple selection, but if you don't need that you could obviously just use an IntegerProperty instead.

这是行工厂:

    final ObservableList<Integer> highlightRows = FXCollections.observableArrayList();

    table.setRowFactory(new Callback<TableView<Person>, TableRow<Person>>() {
        @Override
        public TableRow<Person> call(TableView<Person> tableView) {
            final TableRow<Person> row = new TableRow<Person>() {
                @Override
                protected void updateItem(Person person, boolean empty){
                    super.updateItem(person, empty);
                    if (highlightRows.contains(getIndex())) {
                        if (! getStyleClass().contains("highlightedRow")) {
                            getStyleClass().add("highlightedRow");
                        }
                    } else {
                        getStyleClass().removeAll(Collections.singleton("highlightedRow"));
                    }
                }
            };
            highlightRows.addListener(new ListChangeListener<Integer>() {
                @Override
                public void onChanged(Change<? extends Integer> change) {
                    if (highlightRows.contains(row.getIndex())) {
                        if (! row.getStyleClass().contains("highlightedRow")) {
                            row.getStyleClass().add("highlightedRow");
                        }
                    } else {
                        row.getStyleClass().removeAll(Collections.singleton("highlightedRow"));
                    }
                }
            });
            return row;
        }
    });

以下是一些按钮的外观:

And here are what some buttons might look like:

    final Button btnHighlight = new Button("Highlight");
    btnHighlight.disableProperty().bind(Bindings.isEmpty(table.getSelectionModel().getSelectedIndices()));
    btnHighlight.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            highlightRows.setAll(table.getSelectionModel().getSelectedIndices());
        }
    });

    final Button btnClearHighlight = new Button("Clear Highlights");
    btnClearHighlight.disableProperty().bind(Bindings.isEmpty(highlightRows));
    btnClearHighlight.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            highlightRows.clear();
        }
    });

这篇关于以编程方式更改TableView行外观的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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