【问题标题】:Node.snapshot(null, null) changes size of SceneNode.snapshot(null, null) 改变场景的大小
【发布时间】:2016-09-16 01:57:48
【问题描述】:

我有Scene,它设置为我的primaryStage 的Scene,在其他节点中,它包含一个VBox 和一个TableView 和一些按钮。当我使用TableRow.snapshot(null, null) 对表中的一行进行快照时,Scene 的大小发生了变化。宽度改变了大约 10 个像素,而高度改变了大约 40 - 有时超过 600 (!) - 像素。

发生这种情况是因为Node.snapshot(null, null) 调用Scene.doCSSLayoutSyncForSnapshot(Node node),这似乎获得了大小中所有节点的首选大小并使用它重新计算大小。这会以某种方式返回错误的值,因为我的节点仅指定了首选大小,并且在调用此方法之前看起来很棒。有什么办法可以预防吗?

大小变化是个问题,但是初级阶段不随它所包含的Scene改变大小也是一个问题。

我尝试创建一个 MCVE 来重现该问题,但尝试了几天后,我仍然无法重现该问题。原始程序包含大约 2000 行代码,我不想在这里发布。

为什么Scene.doCSSLayoutSyncForSnapshot(Node node) 会在我的布局一开始就正确布局时损害我的布局?在调用此方法之前,我能否以某种方式确保布局已正确同步,以确保它不会更改任何内容?

【问题讨论】:

  • 好吧,您可以尝试在调用该功能之前在您的节点上设置约束并撤消它们,我的意思是,setMinSize(Pane.USE_PREF_SIZE,Pane.USE_PREF_SIZE);setMaxSize(Pane.USE_PREF_SIZE,Pane.USE_PREF_SIZE); 这可能有助于您描述问题的方式,:)
  • 感谢您没有发布所有 2000 行代码。但是,如果您可以编写一个简短的可编译示例来重现该问题,那将很有帮助。否则,如果您无法重现小样本,请提供指向您所有代码的链接?
  • 我建议使用Scenic View,它允许您在 GUI 运行时查看视图上的所有属性。这至少可以让您检查您描述的问题是否真的是问题。您也可以使用 Scenic View 发布一些屏幕截图。此工具还允许您查看 GUI 中发生的所有事件。我经常使用它:-)
  • 感谢您提供的工具!我将来可能会很好地使用它。但我已经确定我描述的问题确实是问题所在,因为我已经为视图中的每个大小属性添加了侦听器(比使用 Scenic View 所做的工作要多得多,所以再次感谢该工具) .遗憾的是,由于工作原因,我没有时间发布指向我的代码的链接,因为我需要在发布之前屏蔽一些变量名称等。我会在赏金到期之前尝试这样做。
  • 如何初始化场景?根据 Scene.doCSSLayoutSyncForSnapshot 的实现,如果您不使用 init(width, height) 方法,您的场景将根据 layoutX/Y、translateX/Y 和 layoutBounds 宽度/高度调整大小。

标签: java javafx size snapshot


【解决方案1】:

解决了这个问题。不得不复制我的整个项目,然后删除部分代码,直到问题消失。

无论如何。我的应用程序中基本上包含三个组件。导航组件、表格组件和状态栏组件。它看起来像这样:

我遇到的问题是,每当我对表格中的一行进行快照时,状态栏的宽度以及表格组件的宽度和高度都会增加。

显然,这是由于状态栏组件的填充。它有 5 个像素的左右填充,一旦我删除填充,问题就消失了。

增加的 10 个像素宽度使包含所有这些的 BorderPane 扩展为相同数量的像素,并且由于表格宽度绑定到 BorderPane 宽度,它增加了相同数量。但我仍然不明白,为什么包含 BorderPaneStage 不适应新的宽度。

在调用Scene.doCSSLayoutSyncForSnapshot(Node node) 之前组件已正确填充,所以我不明白为什么要添加十个像素的额外宽度。

无论如何:从状态栏组件中删除填充,而不是填充状态栏内的组件解决了这个问题。如果有人对此有很好的解释,我会全力以赴。

这是一个 MCVE,您可以通过在表格中拖动一行来重现该问题:

import java.io.File;
import java.sql.SQLException;
import java.util.ArrayList;

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class MCVE extends Application {

    private Stage primaryStage;
    private BorderPane rootLayout;
    private VBox detailsView;
    private StatusBar statusBar;

    public void start(Stage primaryStage) throws SQLException {

        this.primaryStage = primaryStage;
        this.primaryStage.setTitle("MCVE");

        initRootLayout();
        showStatusBar();
        showDetailsView();

        detailsView.prefWidthProperty().bind(rootLayout.widthProperty());
        detailsView.prefHeightProperty().bind(rootLayout.heightProperty());
    }

    @Override
    public void init() throws Exception {
        super.init();

    }

    public void initRootLayout() {
        rootLayout = new BorderPane();

        primaryStage.setWidth(1000);
        primaryStage.setHeight(600);

        Scene scene = new Scene(rootLayout);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public void showStatusBar() {
        statusBar = new StatusBar();
        rootLayout.setBottom(statusBar);
    }

    public void showDetailsView() {
        detailsView = new VBox();
        rootLayout.setCenter(detailsView);

        setDetailsView(new Table(this));

        detailsView.prefHeightProperty().bind(primaryStage.heightProperty());
        detailsView.setMaxHeight(Region.USE_PREF_SIZE);
    }

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

    public VBox getDetailsView() {
        return detailsView;
    }

    public void setDetailsView(Node content) {
        detailsView.getChildren().add(0, content);
    }

    public StatusBar getStatusBar() {
        return statusBar;
    }

    class StatusBar extends HBox {
        public StatusBar() {
            setPadding(new Insets(0, 5, 0, 5));

            HBox leftBox = new HBox(10);

            getChildren().addAll(leftBox);

            /**
             * CONTROL SIZES
             */
            setPrefHeight(28);
            setMinHeight(28);
            setMaxHeight(28);

            // Leftbox takes all the space not occupied by the helpbox.
            leftBox.prefWidthProperty().bind(widthProperty());

            setStyle("-fx-border-color: black;");
        }
    }

    class Table extends TableView<ObservableList<String>> {

        private ObservableList<ObservableList<String>> data;

        public Table(MCVE app) {

            prefWidthProperty().bind(app.getDetailsView().widthProperty());
            prefHeightProperty()
                    .bind(app.getDetailsView().heightProperty());

            widthProperty().addListener((obs, oldValue, newValue) -> {
                System.out.println("Table width: " + newValue);
            });

            setRowFactory(r -> {
                TableRow<ObservableList<String>> row = new TableRow<ObservableList<String>>();

                row.setOnDragDetected(e -> {
                    Dragboard db = row.startDragAndDrop(TransferMode.ANY);
                    db.setDragView(row.snapshot(null, null));

                    ArrayList<File> files = new ArrayList<File>();

                    // We create a clipboard and put all of the files that
                    // was selected into the clipboard.
                    ClipboardContent filesToCopyClipboard = new ClipboardContent();
                    filesToCopyClipboard.putFiles(files);

                    db.setContent(filesToCopyClipboard);
                });

                row.setOnDragDone(e -> {
                    e.consume();
                });

                return row;
            });

            ObservableList<String> columnNames = FXCollections.observableArrayList("Col1", "col2", "Col3", "Col4");

            data = FXCollections.observableArrayList();

            for (int i = 0; i < columnNames.size(); i++) {
                final int colIndex = i;

                TableColumn<ObservableList<String>, String> column = new TableColumn<ObservableList<String>, String>(
                        columnNames.get(i));

                column.setCellValueFactory((param) -> new SimpleStringProperty(param.getValue().get(colIndex).toString()));

                    getColumns().add(column);
            }

            // Adds all of the data from the rows the data list.
            for (int i = 0; i < 100; i++) {
                // Each column from the row is a String in the list.
                ObservableList<String> row = FXCollections.observableArrayList();

                row.add("Column 1");
                row.add("Column 2");
                row.add("Column 3");
                row.add("Column 4");

                // Adds the row to data.
                data.add(row);
            }

            // Adds all of the rows in data to the table.
            setItems(data);
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多