我試圖在TableView中顯示旅行連接。到目前爲止,這就像一個魅力。現在我有點卡住試圖獲取連接的細節顯示在表格行之間。這應該發生在選擇一個表項上。JavaFX TableView:打開點擊行之間的詳細信息
問題是,細節與我顯示的連接格式不同。所以我需要在兩個表格行之間放置一個面板。這是可能嗎?
我試圖在TableView中顯示旅行連接。到目前爲止,這就像一個魅力。現在我有點卡住試圖獲取連接的細節顯示在表格行之間。這應該發生在選擇一個表項上。JavaFX TableView:打開點擊行之間的詳細信息
問題是,細節與我顯示的連接格式不同。所以我需要在兩個表格行之間放置一個面板。這是可能嗎?
執行此操作的「正確」方法是創建一個TableRow
的自定義外觀,並在安裝了自定義外觀的表上返回TableRow
的表上使用rowFactory
。但是,由於皮膚類在撰寫本文時不是公共API(儘管它們將在Java 9中),這意味着完全從頭開始實現皮膚類(佈置表格單元格等),這將會非常漂亮難。
一個不太「官方」的方法,但稍微簡單一點,就是直接覆蓋TableRow
中的各種佈局方法,並掛接到超類實現中。
這工作,但感覺有點脆弱:
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);
}
}
這給出了以下:
這工作出色。你介意我是否在博客上發佈了這個解決方案?這不會是一個直接的副本,而是一個通用版本。 –
這很好;請參考這篇文章。 (順便說一下,我只是在啓用了多項選擇的情況下才進行非常簡短的測試;如果您還沒有選擇,您可能也想在那裏測試它。) –
也許你應該考慮使用['TreeView'(HTTP://文檔.oracle.com/JavaFX的/ 2/ui_controls /樹view.htm)。但我想你需要一個'TableView'提供的列。但是,「TreeView」中的節點可以修改爲看起來像一個表。 –
['TreeTableView'](http://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/TreeTableView.html)具有樹形視圖結構和表格提供的列,如果爲你需要的東西工作。但是「細節與我正在顯示的連接不同的格式」暗示這不會是你需要的。 –