【问题标题】:FXML StackPane doesn't align children correctlyFXML StackPane 未正确对齐子级
【发布时间】:2016-05-28 07:21:10
【问题描述】:

我希望 RectangleLabel 在 StackPane 中对齐,但是我的代码没有达到预期的结果:

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();
        }
    }
}

更新

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

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);

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

【问题讨论】:

    标签: java javafx javafx-8 fxml


    【解决方案1】:

    基本上,如果您需要带有彩色背景的TextLabel,最简单的方法是将CSS 用于单个LabelText,无需任何Rectangle 对象。

    将标签与 CSS 结合使用的示例

    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 对这个问题的回答非常详细:

    JavaFX 2: resizable rectangle containing text

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

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

    作为解决方法,您可以请求 StackPane 的布局更新,就像您在侦听器中尝试过的那样。

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

    pane.layout();
    

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

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

    示例

    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);
        }
    }
    

    【讨论】:

    • 感谢您提供非常详细的答案。我认为 CSS 解决方案会很好。
    猜你喜欢
    • 1970-01-01
    • 2020-11-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-19
    相关资源
    最近更新 更多