我有一个带有多个 TableColumn 的 TableView,我想在某个 TableColumn 下方放置一个节点。如何获取 TableColumn 的确切位置(x,y 坐标),以便绑定(bind)节点的翻译属性?
以下是我如何在 TableView 右上角放置按钮的片段:
button.translateXProperty().unbind();
button.translateXProperty().bind(tableView.widthProperty().divide(2.0).subtract(button.getWidth() / 2.0 + 2.0) + tableView.localToScene(0.0, 0.0).getX());
这工作得很好,但显然只适用于 TableView。 TableColumns 没有这些翻译属性或 localToScene 方法,因此我无法直接获取我想要绑定(bind)节点的位置。
我当前的解决方案(实际上效果不太好)是执行以下操作: 我读出 TableView 在场景中的位置 (PointA),然后浏览所有列的列表 (tableView.getColumns()) 并检查每个列是否可见,如果是,则将它们的宽度添加到 X- A 点的值。我这样做,直到找到我想要在下面放置节点的实际列。 现在的问题是,我实际上不能将节点位置绑定(bind)到这一点,因为当我更改列的顺序或使其中之一不可见时,我的列会更改屏幕上的位置。我必须为列顺序和可见性添加一个监听器...
有没有更有效的方法来完成我想要的事情? :D
最佳答案
我通常不喜欢使用查找,但您可以使用查找 .table-view .column-header .label
检索用于显示列标题的标签,然后绑定(bind)按钮的布局属性使用该标签的边界。
示例:
import java.util.Optional;
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Parent;
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.layout.Pane;
import javafx.stage.Stage;
public class TableColumnLocationExample extends Application {
@Override
public void start(Stage primaryStage) {
TableView<Person> table = new TableView<>();
table.getColumns().add(column("First Name", Person::firstNameProperty, 120));
table.getColumns().add(column("Last Name", Person::lastNameProperty, 120));
table.getColumns().add(column("Email", Person::emailProperty, 250));
table.getItems().addAll(
new Person("Jacob", "Smith", "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="442e25272b266a37292d302c04213c25293428216a272b29" rel="noreferrer noopener nofollow">[email protected]</a>"),
new Person("Isabella", "Johnson", "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a4cdd7c5c6c1c8c8c58acecbcccad7cbcae4c1dcc5c9d4c8c18ac7cbc9" rel="noreferrer noopener nofollow">[email protected]</a>"),
new Person("Ethan", "Williams", "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="31544559505f1f46585d5d58505c42715449505c415d541f525e5c" rel="noreferrer noopener nofollow">[email protected]</a>"),
new Person("Emma", "Jones", "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="385d555559165257565d4b785d40595548545d165b5755" rel="noreferrer noopener nofollow">[email protected]</a>"),
new Person("Michael", "Brown", "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="365b5f555e57535a18544459415876534e575b465a531855595b" rel="noreferrer noopener nofollow">[email protected]</a>")
);
Pane root = new Pane(table);
Scene scene = new Scene(root, 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
for (TableColumn<Person, ?> col : table.getColumns()) {
Optional<Label> header = findLabelForTableColumnHeader(col.getText(), root);
header.ifPresent(label -> {
Button button = new Button(col.getText());
button.prefWidthProperty().bind(Bindings.createDoubleBinding(() ->
label.getBoundsInLocal().getWidth(), label.boundsInLocalProperty()));
button.minWidthProperty().bind(button.prefWidthProperty());
button.maxWidthProperty().bind(button.prefWidthProperty());
button.layoutXProperty().bind(Bindings.createDoubleBinding(() ->
label.getLocalToSceneTransform().transform(label.getBoundsInLocal()).getMinX(),
label.boundsInLocalProperty(), label.localToSceneTransformProperty()));
button.layoutYProperty().bind(Bindings.createDoubleBinding(() ->
table.getBoundsInParent().getMaxY() ,table.boundsInParentProperty()));
root.getChildren().add(button);
});
}
}
private Optional<Label> findLabelForTableColumnHeader(String text, Parent root) {
return root.lookupAll(".table-view .column-header .label")
.stream()
.map(Label.class::cast)
.filter(label -> label.getText().equals(text))
.findAny(); // assumes all columns have unique text...
}
private <S,T> TableColumn<S,T> column(String title, Function<S,ObservableValue<T>> property, double width) {
TableColumn<S,T> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
col.setPrefWidth(width);
return col ;
}
public static class Person {
private StringProperty firstName = new SimpleStringProperty();
private StringProperty lastName = new SimpleStringProperty();
private StringProperty email = new SimpleStringProperty();
public Person(String firstName, String lastName, String email) {
setFirstName(firstName);
setLastName(lastName);
setEmail(email);
}
public final StringProperty firstNameProperty() {
return this.firstName;
}
public final String getFirstName() {
return this.firstNameProperty().get();
}
public final void setFirstName(final String firstName) {
this.firstNameProperty().set(firstName);
}
public final StringProperty lastNameProperty() {
return this.lastName;
}
public final String getLastName() {
return this.lastNameProperty().get();
}
public final void setLastName(final String lastName) {
this.lastNameProperty().set(lastName);
}
public final StringProperty emailProperty() {
return this.email;
}
public final String getEmail() {
return this.emailProperty().get();
}
public final void setEmail(final String email) {
this.emailProperty().set(email);
}
}
public static void main(String[] args) {
launch(args);
}
}
关于javafx - TableColumn 在场景中的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30802776/