FXML StackPane无法正确对齐子项

时间:2016-05-28 07:21:10

标签: java javafx javafx-8 fxml

我希望在StackPane中对齐RectangleLabel,但是我的代码无法达到预期效果:

enter image description here

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

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

1 个答案:

答案 0 :(得分:1)

基本上,如果您需要带有彩色背景的TextLabel,则最简单的方法是将CSS用于单个LabelText,而不使用任何{{1}对象。

使用带CSS的标签的示例

Main.java

Rectangle

application.css

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

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

JavaFX 2: resizable rectangle containing text

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

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

作为解决方法,您可以像在侦听器中尝试的那样请求.rounded-background-label { -fx-background-color: black, white; -fx-background-insets: 0, 1; -fx-padding: 10px; -fx-background-radius: 12px; } 的布局更新。

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

StackPane

pane.layout();

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

示例

LabelRectangleTest.fxml

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

    }
});

LabelRectangleTestController.java

<?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>

Main.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();

                }
            });
        });

    }

}