JavaFX TableView:单击行之间打开详细信息 [英] JavaFX TableView: open detail information between rows on click

查看:137
本文介绍了JavaFX TableView:单击行之间打开详细信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在TableView中显示旅行连接。到目前为止,它就像一个魅力。现在我有点想要获取要在表行之间显示的连接的详细信息。这应该在选择一个表项时发生。

I'm trying to display travel connections in a TableView. So far that works like a charm. Now I'm kinda stuck trying to get details of a connection to be displayed in between table rows. This should happen on selecting a table item.

问题是,细节的格式与我正在显示的连接格式不同。所以我需要在两个表行之间放置一个面板。这有可能吗?

The problem is, that the details are in a different format than the connections I'm displaying. So I would need to put a panel between two table rows. Is this at all possible?

推荐答案

正确的方法是为<$ c创建一个自定义皮肤$ c> TableRow 并在返回 TableRow 的表上使用 rowFactory 自定义皮肤安装。但是,由于皮肤类在编写时并不是公共API(注意它们将在Java 9中),这意味着完全从头开始实现皮肤类(布置表格单元格等),这将是相当的很难。

The "proper" way to do this would be to create a custom skin for TableRow and use a rowFactory on the table that returned a TableRow with the custom skin installed. However, since skin classes are not public API at the time of writing (note though that they will be in Java 9), this would mean implementing the skin class entirely from scratch (laying out the table cells, etc), which would be pretty difficult.

一种不那么官方的方法,但更容易一点,就是覆盖 TableRow中的各种布局方法,并挂钩超类实现。

A less "official" approach, but one that's a little easier, is just to override the various layout methods in the TableRow directly, and hook into the superclass implementation.

这样可行,但感觉有点脆弱:

This works, but feels a little fragile:

import java.util.Random;
import java.util.function.Function;

import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
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.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class TableWithCustomRow extends Application {

    @Override
    public void start(Stage primaryStage) {
        TableView<Item> table = new TableView<>();

        table.setRowFactory(tv -> new TableRow<Item>() {
            Node detailsPane ;
            {
                selectedProperty().addListener((obs, wasSelected, isNowSelected) -> {
                    if (isNowSelected) {
                        getChildren().add(detailsPane);
                    } else {
                        getChildren().remove(detailsPane);
                    }
                    this.requestLayout();
                });
                detailsPane = createDetailsPane(itemProperty());
            }

            @Override
            protected double computePrefHeight(double width) {
                if (isSelected()) {
                    return super.computePrefHeight(width)+detailsPane.prefHeight(getWidth());
                } else {
                    return super.computePrefHeight(width);
                }
            }

            @Override
            protected void layoutChildren() {
                super.layoutChildren();
                if (isSelected()) {
                    double width = getWidth();
                    double paneHeight = detailsPane.prefHeight(width);
                    detailsPane.resizeRelocate(0, getHeight()-paneHeight, width, paneHeight);
                } 
            }
        });

        Random random = new Random();
        for (int i = 1 ; i <= 100 ; i++) {
            table.getItems().add(new Item("Item "+i, random.nextInt(100)));
        }
        table.getColumns().add(column("Item", Item::nameProperty));
        table.getColumns().add(column("Value", Item::valueProperty));

        Scene scene = new Scene(table, 800, 600);
        primaryStage.setScene(scene);
        primaryStage.show();

    }

    private Node createDetailsPane(ObjectProperty<Item> item) {
        BorderPane detailsPane = new BorderPane();
        Label detailsLabel = new Label();
        VBox labels = new VBox(5, new Label("These are the"), detailsLabel);
        labels.setAlignment(Pos.CENTER_LEFT);
        labels.setPadding(new Insets(2, 2, 2, 16));
        detailsPane.setCenter(labels);

        Label icon = new Label("Icon");
        icon.setStyle("-fx-background-color: aqua; -fx-text-fill: darkgreen; -fx-font-size:18;");
        BorderPane.setMargin(icon, new Insets(6));
        icon.setMinSize(40, 40);
        detailsPane.setLeft(icon);

        detailsPane.setStyle("-fx-background-color: -fx-background; -fx-background: skyblue;");

        item.addListener((obs, oldItem, newItem) -> {
            if (newItem == null) {
                detailsLabel.setText("");
            } else {
                detailsLabel.setText("details for "+newItem.getName());
            }
        });


        return detailsPane ;
    }

    private static <S,T> TableColumn<S,T> column(String title, Function<S, ObservableValue<T>> property) {
        TableColumn<S,T> col = new TableColumn<>(title);
        col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
        col.setPrefWidth(150);
        return col ;
    }

    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 java.lang.String getName() {
            return this.nameProperty().get();
        }


        public final void setName(final java.lang.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) {
        launch(args);
    }
}

这给出以下内容:

这篇关于JavaFX TableView:单击行之间打开详细信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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