javafx-2 - 如何可靠地获取 JavaFX 标签或工具栏的边界?

标签 javafx-2

下面的示例代码。这对所有内容输出全零。对于工具栏,它还显示零。对于文本,它输出非零宽度和高度。这是 Label 上的错误还是故意的?我应该做些什么来让标签有其界限吗?我尝试过其他线程、移动、各种事情。

注意:所有节点都按预期显示。这只是边界的获取不起作用。

我看到一些关于可能在boundsInParent属性上使用监听器的内容。当我尝试这样做时,许多事件中的数字都会波动,因此似乎没有办法确定我何时会获得正确的值。

import javafx.application.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;


public class TestBounds extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    public void start(Stage stage) {
        Pane root = new Pane();
        Group g = new Group();
        root.getChildren().add(g);

        Scene scene = new Scene(root, 500, 500);
        stage.setScene(scene);
        stage.show();

        Platform.runLater(() -> {
//            Text text = new Text("test label");
//            ToolBar text = new ToolBar(new Button("test label"));
            Label text = new Label("test label");
            g.getChildren().add(text);
            System.out.println(text.getBoundsInParent());
            System.out.println(text.getBoundsInLocal());
            System.out.println(text.getLayoutBounds());
        });
    }
}

@sarcan 的答案是一个好的开始,但它并不完整。这是一个例子:

package other;

import javafx.application.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;


public class Main extends Application {

    @Override
    public void start(Stage stage) {
        Pane root = new Pane();
        final Group g = new Group();
        root.getChildren().add(g);

        Scene scene = new Scene(root, 500, 500);
        stage.setScene(scene);
        stage.show();

        Platform.runLater(() -> {
            final Label text = new Label("test label");
            g.getChildren().add(text);
            new Thread(() -> {
                Platform.runLater(() -> {
                    System.out.println("text.getWidth() = " + text.getWidth());
                    System.out.println(text.getBoundsInParent());
                    System.out.println(text.getBoundsInLocal());
                    System.out.println(text.getLayoutBounds());
                });
            }).start();
        });
    }

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

您可以删除 new Thread() 部分,它仍然会显示问题。我把它放在那里只是为了表明我真的想按照建议“推迟”它。上面的示例按照建议使用了 runLater,但仍然演示了该问题。边界全部输出为 0。

上面的例子很常见——当已经在 FX 线程中并且需要访问其边界时添加一个节点。但是,如何可靠地延迟以便在场景更新后获得这些边界呢? Platform.runLater 显然没有这样做。

最佳答案

这里的问题是您将文本添加到其父级,然后立即查询其坐标。 JavaFX 和大多数其他工具包的工作方式与您预期的有点不同:添加标签时,场景图不会立即更新。相反,它被标记为“脏”。当 JavaFX 应用程序线程存在于您的 block 中时,它将执行更新,包括布置您的组并相应地设置标签的边界。

这样做的原因很简单。如果JavaFX立即更新场景图,不仅会造成浪费,还会导致奇怪的结果。假设您要添加 20 个标签,这会触发 20 个立即更新。由于这些发生得非常快,用户界面会闪烁。相反,发生的情况是您添加 20 个标签,这会导致 ui 被标记为脏 20 次(这非常便宜),然后所有更改都将应用在一次更新中。将 runLater block 视为“向 JavaFX 描述您希望 ui 在下一次原子更新后的外观”。

现在,话虽这么说,如果您想获取文本的范围,只需首先给 JavaFX 一个更新的机会即可。例如,如果您将添加的文本移到 runLater block 前面,则会添加文本,更新场景图,然后您将查询坐标 - 这将产生正确的结果:

public void start(Stage stage) {
    Pane root = new Pane();
    final Group g = new Group();
    final Label text = new Label("test label");
    g.getChildren().add(text);
    root.getChildren().add(g);

    Scene scene = new Scene(root, 500, 500);
    stage.setScene(scene);
    stage.show();

    Platform.runLater(new Runnable() {
        public void run() {
            System.out.println("text.getWidth() = " + text.getWidth());
            System.out.println(text.getBoundsInParent());
            System.out.println(text.getBoundsInLocal());
            System.out.println(text.getLayoutBounds());
        }
    });
}

关于javafx-2 - 如何可靠地获取 JavaFX 标签或工具栏的边界?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17381686/

相关文章:

javafx-2 - JavaFX 2.x : XYChart properties

java - 使用 css 在 javafx 中调整 stackpane 的大小

javafx-2 - 如何在 JavaFX Canvas 上绘制旋转的图像?

java - JFXPanel 拖放

java - JavFX 2 菜单按钮

JavaFx:如果我想在 initialize() 之后,场景显示之前做一些事情,我该如何实现呢?

javafx-2 - 在异步加载 ListView 项目期间显示 ProgressIndicator

JavaFX getResource 在浏览器中运行时返回 null

java - 在 javafx 中注册鼠标处理程序,但处理程序不是内联的

java - 如何在Sqlite数据库中存储数据(Android上的JavaFX)