FXML StackPane无法正确对齐子项 [英] FXML StackPane doesn't align children correctly

查看:127
本文介绍了FXML StackPane无法正确对齐子项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个 Rectangle 和一个 Label 来在StackPane中对齐,但是我的代码没有达到期望的结果:

I want a Rectangle and a Label to align in the StackPane, however my code doesn't achieve the desired result:

FXML:

<fx:root type="HBox" xmlns:fx="http://javafx.com/fxml">
    <StackPane fx:id="pane">
        <children>
            <Rectangle fx:id="bubble" fill="#ffffff"></Rectangle>
            <Label fx:id="message" style="-fx-border-color:black; -fx-border-width: 1; -fx-border-style: solid;"></Label>
        </children>
    </StackPane>
</fx:root>

控制器:

public class MessageBubble extends HBox implements Initializable {
    @FXML
    private StackPane pane;
    @FXML
    private Label message;
    @FXML
    private Rectangle bubble;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        message.setText("message");
        pane.setAlignment(Pos.CENTER);

        bubble.setArcWidth(15.0);
        bubble.setArcHeight(15.0);

        bubble.setStroke(Color.BLACK);

        message.widthProperty().add(10.0).addListener((observable, oldValue, newValue) -> {
            bubble.setWidth(newValue.doubleValue());
            pane.layout();
        });
        message.heightProperty().add(10.0).addListener((observable, oldValue, newValue) -> {
            bubble.setHeight(newValue.doubleValue());
            pane.layout();
        });
    }

    public MessageBubble() {
        FXMLLoader loader = new FXMLLoader(this.getClass().getResource("MessageBubble.fxml"));
        loader.setRoot(this);
        loader.setController(this);

        try {
            loader.load();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

更新

如果我以编程方式进行大小调整,它会很好地对齐:

If I do sizing programmatically, it aligns fine:

this.pane.getChildren().addAll(this.bubble, this.message);
bubble.setFill(Color.ALICEBLUE);
bubble.setArcWidth(15.0);
bubble.setArcHeight(15.0);

bubble.setStroke(Color.BLACK);

message.setStyle("-fx-border-color:black; -fx-border-width: 1; -fx-border-style: solid;");

message.setText("message");

message.setPrefWidth(60.0);
message.setPrefHeight(25.0);

bubble.setWidth(70.0);
bubble.setHeight(30.0);

但是这样,我需要自己计算尺寸。

But this way, I need to calculate the size myself.

推荐答案

基本上,如果你需要一个 Text Label 使用彩色背景,最简单的方法是将CSS用于单个标签文本,不带任何矩形对象。

Basically, if you need a Text or Label with colored backround, the easiest approach to use CSS for a single Label or Text, without any Rectangle objects.

使用带CSS的Label的示例

Main.java

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            HBox root = new HBox();

            Scene scene = new Scene(root,400,400);
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());

            Label message = new Label();
            TextArea textArea = new TextArea();
            textArea.setPrefWidth(200);
            textArea.setText("message");
            message.textProperty().bind(textArea.textProperty());
            message.getStyleClass().add("rounded-background-label");

            root.getChildren().addAll(message, textArea);

            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

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

application.css

.rounded-background-label {
    -fx-background-color: black, white;
    -fx-background-insets: 0, 1;
    -fx-padding: 10px;
    -fx-background-radius: 12px;
}

@jewelsea对这个问题的回答非常详细:

The answer from @jewelsea on this question is really detailed:

JavaFX 2:包含文本的可调整大小的矩形

但是如果你想继续使用Label + Rectangle解决方案

我担心这与此错误有关: http://错误。 java.com/bugdatabase/view_bug.do?bug_id=JDK-8137252

I fear it is related to this bug: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8137252

作为解决方法,您可以请求布局更新您已经在侦听器中尝试过 StackPane

As workaround you can request the layout update of the StackPane, as you have tried in the listeners.

您的代码唯一的问题是您应该替换:

The only problem with your code is that you should replace:

pane.layout();

with

Platform.runLater(new Runnable() {
    @Override
    public void run() {
        pane.requestLayout();

    }
});

这将确保布局将在GUI线程上发生。

which will ensure that the layout will happen on the GUI Thread.

示例

LabelRectangleTest.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.shape.*?>

<HBox prefHeight="100.0" prefWidth="200.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="application.LabelRectangleTestController">
  <children>
    <HBox prefHeight="100.0" prefWidth="200.0">
      <children>
        <StackPane fx:id="pane" minHeight="126.0" prefHeight="126.0" prefWidth="200.0" HBox.hgrow="ALWAYS">
          <children>
            <Rectangle fx:id="bubble" arcHeight="15.0" arcWidth="15.0" fill="WHITE" height="27.75" stroke="BLACK" strokeType="INSIDE" width="68.0" />
            <Label fx:id="message" text="Label" />
          </children>
        </StackPane>
        <TextArea fx:id="textArea" prefWidth="200.0" wrapText="true" />
      </children>
    </HBox>
  </children>
</HBox>

LabelRectangleTestController.java

public class LabelRectangleTestController implements Initializable {

    @FXML
    private Label message;
    @FXML
    private Rectangle bubble;
    @FXML
    private StackPane pane;
    @FXML
    private TextArea textArea;

    @Override
    public void initialize(URL location, ResourceBundle resources) {

        textArea.setText("message");
        message.textProperty().bind(textArea.textProperty());

        message.widthProperty().addListener((observable, oldValue, newValue) -> {
            bubble.setWidth(newValue.intValue() + 10);
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    pane.requestLayout();
                }
            });
        });
        message.heightProperty().addListener((observable, oldValue, newValue) -> {
            bubble.setHeight(newValue.doubleValue() + 10);
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    pane.requestLayout();

                }
            });
        });

    }

}

Main.java

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("LabelRectangleTest.fxml"));
            HBox root = loader.load();
            Scene scene = new Scene(root,400,400);

            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

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

这篇关于FXML StackPane无法正确对齐子项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆