如何在JavaFX中将按钮右对齐?

8
我该如何让窗口中的“右”(第二个)按钮右对齐?
class HelloApp extends Application {
  override def start(primaryStage: Stage): Unit = {
    val root = new FlowPane(Orientation.VERTICAL) {
      setPadding(new Insets(10, 10, 10, 10))
      setVgap(10)
      getChildren.add(new Button("Left"))
      getChildren.add(new Button("Right") { setAlignment(Pos.CENTER_RIGHT) }) // this doesn't seem to be working
    }

    primaryStage.setScene(new Scene(root, 400, 400))
    primaryStage.show()
  }
}

谢谢

3个回答

23

示例解决方案

以下是一个示例,提供了一个左对齐和右对齐的按钮:

alignment

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.*;
import javafx.stage.Stage;

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

  @Override
  public void start(Stage primaryStage) throws Exception {
    HBox root = new HBox();
    root.setPadding(new Insets(10, 10, 10, 10));

    final Button left = new Button("Left");
    left.setMinSize(Button.USE_PREF_SIZE, Button.USE_PREF_SIZE);
    final Pane spacer = new Pane();
    HBox.setHgrow(spacer, Priority.ALWAYS);
    spacer.setMinSize(10, 1);
    final Button right = new Button("Right");
    right.setMinSize(Button.USE_PREF_SIZE, Button.USE_PREF_SIZE);

    root.getChildren().addAll(left, spacer, right);

    primaryStage.setScene(new Scene(root, 400, 400));
    primaryStage.show();
  }
}

由于我不使用Scala编程语言,因此此解决方案提供了Java代码。 但是应该很容易将其翻译为等效的Scala代码。

解释

我选择了HBox,因为对我来说,这是最常见的左右对齐的实例。 但这里没有真正的对和错,使用其他布局类型(如AnchorPane)也可以实现所需的结果。

为了实现使用HBox进行右对齐,我在左对齐节点和右对齐节点之间插入了一个可变宽度的间距窗格,将所有右对齐的节点推到右侧。 我添加了各种额外的最小尺寸约束,以始终显示完整的按钮文本,并使当您将窗口缩小时,左侧和右侧对齐节点之间始终有一小间隙。

关于setAlignment()

你没有看到button.setAlignment()方法起作用的原因是它不会做你想象中的事情。setAlignment是为了在按钮超过其首选宽度时对按钮内文本进行对齐。请参阅setAlignment javadoc:
指定当Labeled中有空白空间时,应如何对齐Labeled中的文本和图形。
默认按钮的最大宽度是其首选宽度,因此除非您使用button.setMaxWidth(Double.MAX_VALUE)明确设置其最大宽度,否则按钮不会增大。这意味着,默认情况下,setAlignment方法将不起任何作用,因为按钮内部内容没有额外的可用空间进行对齐。
要进一步了解此内容,请阅读:Tips for Sizing and Aligning Nodes(强烈推荐)。
关于其他Pane类型的对齐,请参见:On aligning for other Pane Types

有许多其他布局窗格(例如AnchorPane、GridPane等),可以用来实现类似的布局。不同的布局窗格具有不同的功能和API。这意味着处理常见布局问题(如对齐)的方式在它们之间是不同的(您需要查阅其API才能了解如何为每种布局窗格类型进行操作)。

如果您想要控制布局窗格内的对齐,必须使用像我上面演示的spacer,或者在节点上设置额外的窗格级约束。各种布局类型上设置约束的示例是以下方法(其中一些是静态的):

以上只是示例,还有许多其他方式可以对齐节点,例如通过设置BorderPane的顶部、中心或右侧属性。

为什么FlowPane并不适合您想要实现的目标

您可以通过将FlowPane的方向设置为垂直并调用flowPane.setColumnHalignment(Pos.CENTER_RIGHT)来右对齐FlowPane中的节点。然而,这会将FlowPane中的所有内容都右对齐,而不是将一个东西左对齐,另一个东西右对齐,这正是您想要做的。


这不是右对齐,而是最右边的对象。 - Bob Flannigon
@BobFlannigon 如果您想将所有内容向右对齐,那么只需要将间隔器作为HBox中的第一件事,而不要添加填充即可。 - jewelsea

6

enter image description here

尽管Jewelsea的回答完整且正确,但它是基于Java的解决方案,我想提供一个基于fxml的解决方案,可能对一些开发人员有帮助。这是Jewelsea回答的fxml版本。
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Pane?>


<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1">
   <padding>
      <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
   </padding>
   <children>
      <Button mnemonicParsing="false" text="Left" />
      <Pane HBox.hgrow="ALWAYS" />
      <Button mnemonicParsing="false" text="Right" />
   </children>
</HBox>

1
我不确定FlowPane是否真正支持这个。使用GridPane,您可以创建两列并使用第一列消耗所有空间。像这样:
    GridPane pneButtons = new GridPane();

    ColumnConstraints col1 = new ColumnConstraints();
    col1.setHgrow(Priority.ALWAYS);
    pneButtons.getColumnConstraints().add(col1);

    Button btnRight = new Button("RIGHT");
    pneButtons.getChildren().add(btnRight);

    GridPane.setColumnIndex(btnRight, 1);

请问如果我真的想只使用FlowPlane,你能否建议一种方法?比如说,将两个按钮对齐到窗口的两侧。如果用户调整窗口大小小于两个按钮所需的可用空间,则需要垂直布局按钮(就像在FlowPane中一样)。 - Sai Dandem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接