如何在Javafx中对齐对话窗格的Ok按钮?

时间:2016-03-15 11:18:33

标签: javafx dialog javafx-2 javafx-8

我想对齐,即位置CENTER和DialogPane的OK按钮。我尝试了下面的代码,但它不起作用。

Dialog dialog = new Dialog();
DialogPane dialogPane = dialog.getDialogPane();
dialogPane.setStyle("-fx-background-color: #fff;");

        // Set the button types.
ButtonType okButtonType = new ButtonType("Ok", ButtonBar.ButtonData.OK_DONE);
ButtonType cancelButtonType = new ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);
dialog.getDialogPane().getButtonTypes().addAll(okButtonType, cancelButtonType);
dialogPane.lookupButton(cancelButtonType).setVisible(false);

        // Testing
Button okButton = (Button) dialog.getDialogPane().lookupButton(okButtonType);
okButton.setAlignment(Pos.CENTER);
        // End Testing

dialog.showAndWait();

5 个答案:

答案 0 :(得分:4)

对话框的ButtonBar中的中心按钮实际上非常难以以非黑客的方式实现。

以下是我能想到的最佳解决方案。它依赖于按钮容器的dynamic CSS lookup HBox,然后在右侧添加一个间隔区域以将按钮向左推(默认的ButtonSkin实现已经放置了一个左侧的隐式间隔器,它推动了右边的按钮,我用ScenicView确定的。左右垫片的组合最终对齐中心的按钮。该解决方案还会覆盖ButtonBar创建,以阻止ButtonSkin在内部重新排序并执行其他按钮布局,因为当它这样做时,您无法真正可靠地自定义布局。

centered button

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

import java.util.Optional;

public class CenteredDialogButtons extends Application {
    @Override
    public void start(Stage stage) {
        Button show = new Button("Show Dialog");

        Dialog<ButtonType> dialog = new Dialog<>();
        DialogPane dialogPane = new DialogPane() {
            @Override
            protected Node createButtonBar() {
                ButtonBar buttonBar = (ButtonBar) super.createButtonBar();
                buttonBar.setButtonOrder(ButtonBar.BUTTON_ORDER_NONE);

                return buttonBar;
            }
        };
        dialog.setDialogPane(dialogPane);
        dialogPane.getButtonTypes().addAll(ButtonType.OK);
        dialogPane.setContentText("Centered Button");

        Region spacer = new Region();
        ButtonBar.setButtonData(spacer, ButtonBar.ButtonData.BIG_GAP);
        HBox.setHgrow(spacer, Priority.ALWAYS);
        dialogPane.applyCss();
        HBox hbox = (HBox) dialogPane.lookup(".container");
        hbox.getChildren().add(spacer);

        show.setOnAction(e -> {
            Optional<ButtonType> result = dialog.showAndWait();
            if (result.isPresent() && result.get() == ButtonType.OK) {
                System.out.println("OK");
            }
        });

        StackPane layout = new StackPane(
                show
        );
        layout.setPadding(new Insets(50));

        Scene scene = new Scene(layout);

        stage.setScene(scene);
        stage.show();
    }

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

我不太喜欢这种解决方案的原因是动态CSS查找违反了API封装,因为按钮栏等控件的JavaFX场景图的CSS结构实际上并不是它们的公共API的一部分。但是,我认为使用现有的JavaFX 8公共API和默认的ButtonBar皮肤,确实可以在ButtonBar中获得居中按钮。

另一种方法是为与对话框关联的ButtonBar创建自定义外观,但这种方法非常困难,我不建议将其用于此任务。

基本上,所有这些的内容是,只要保留默认按钮布局和对话框的顺序,而不是尝试自定义对话框按钮布局。如果您确实希望将完全自定义的布局设置为按钮放置等级别,那么您最好只通过继承Stage而不是将自定义对话框实现基于内置对话框类来创建自己的自定义对话框类。 / p>

相关但信息略有不同:

答案 1 :(得分:0)

这是一种黑客行为,但你可以这样做:

okButton.translateXProperty().bind(okButton.prefWidthProperty().divide(-2));

DialogPane是水平居中的,所以减去okButton的半宽就可以了。 但我认为这是一个非常肮脏的解决方案; - )

答案 2 :(得分:0)

根据@ManuelSeiche的答案,以下是如何计算到中心的精确距离:

@FXML private Dialog<ButtonType> dialog;
@FXML private ButtonType btClose;

@FXML
private void initialize()
{
    dialog.setOnShown(event ->
    {
        Platform.runLater(() ->
        {
            Button btnClose = (Button) dialog.getDialogPane().lookupButton(btClose);
            HBox hBox = (HBox) btnClose.getParent();
            double translateAmount = hBox.getWidth() / 2.0 - btnClose.getWidth() / 2.0 - hBox.getPadding().getLeft();
            btnClose.translateXProperty().set(-translateAmount);
        });
    });
}

答案 3 :(得分:0)

我尝试将Alert中的“确定”按钮居中,但不确定这是bug还是功能(Java8),但可以通过设置新按钮来使单个按钮居中:

alert.getButtonTypes().set(0, new ButtonType("OK", ButtonBar.ButtonData.LEFT));

只要ButtonData.LEFT中只有一个按钮,它就位于按钮面板的中间。显然,该解决方案不适用于具有多个按钮的面板,但是它可能有助于放置单个“确定”按钮。

答案 4 :(得分:0)

将此方法添加到代码中,并在需要对齐“对话框”或“警报”中的按钮时调用它:

    private void centerButtons(DialogPane dialogPane) {
      Region spacer = new Region();
      ButtonBar.setButtonData(spacer, ButtonBar.ButtonData.BIG_GAP);
      HBox.setHgrow(spacer, Priority.ALWAYS);
      dialogPane.applyCss();
      HBox hboxDialogPane = (HBox) dialogPane.lookup(".container");
      hboxDialogPane.getChildren().add(spacer);
   }

以这种方式调用:centerButtons(dialog.getDialogPane);