JavaFX TableView:单击行之间打开详细信息 [英] JavaFX TableView: open detail information between rows on click
问题描述
我正在尝试在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中的各种布局方法直接code>,并挂钩超类实现。
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屋!