让Display方法返回布尔值? - JavaFX

3

我有一个叫做GUI的类来管理我的应用程序。当用户想要删除他在我的程序中的账户时,我希望出现一个警告框,要求他确认或取消操作,以免意外删除他的账户。

 package application;

 import javafx.geometry.Pos;
 import javafx.scene.Scene;
 import javafx.scene.control.Button;
 import javafx.scene.control.Label;
 import javafx.scene.layout.HBox;
 import javafx.scene.layout.VBox;
 import javafx.stage.*;

 /**
  * An Alert Box for the GUI
  * to display errors to the user.
  *
  */
public class AlertBox
{   
Stage window;

public boolean display(String title, String message)
{       
    boolean cancel = false;

    window = new Stage();                                                               // Create the stage.        

    window.initModality(Modality.APPLICATION_MODAL);                                    // If window is up, make user handle it.
    window.setTitle(title);
    window.setMinHeight(350);
    window.setMinWidth(250);

    VBox root = new VBox();                 // Root layout.

    Label warning = new Label(message);     // Message explaining what is wrong.

    HBox buttonLayout = new HBox();         // The yes and cancel button.

    Button yesButton = new Button("Yes");   // Yes button for the user.
    Button noButton = new Button("No");     // No button for the user.

    yesButton.setOnAction(e ->
    {
        cancel = false;
    });

    noButton.setOnAction(e ->
    {
        cancel = true;
    });
    buttonLayout.getChildren().addAll(yesButton, noButton);


    root.getChildren().addAll(warning, buttonLayout);
    root.setAlignment(Pos.CENTER);

    Scene scene = new Scene(root);
    window.setScene(scene);
    window.show();
}

/**
 * Closes the window and returns whether the user said yes or no.
 * @param variable
 * @return
 */
private boolean close(boolean variable)
{
    window.close();
    return variable;
}

我希望我的GUI类能够准确地知道用户在AlertBox类中的操作。用户是点击了“是”还是“否”?因此,我考虑将显示方法设为布尔值。问题在于,我的事件监听器表达式无法返回任何值,因为它位于类型为void的回调内部。然后我想,“哦,我只需使关闭方法返回一个布尔值”。但是,我记得我调用的原始函数是:

AlertBox warning = new AlertBox;
boolean userWantsToDelete = warning.display("Warning!", "You are about to delete your account. Are you sure you would like to do this?");

这里需要返回一个变量而不是close方法,我也不能直接调用close方法,因为那样行不通。有什么办法可以解决这个问题吗?非常感谢。


这很接近于重复的内容:在用户单击按钮之前阻止程序执行 - jewelsea
这并不回答你的问题,但是将EventHandler接口传递给display方法怎么样? - Tomasz Mularczyk
实际上,在调用“display”方法之前,最好将其设置在您的类中。 - Tomasz Mularczyk
4个回答

6

您可以使用JavaFX警报轻松执行任务:

    Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
    alert.setTitle("Confirmation Dialog");
    alert.setHeaderText("Warning !");
    alert.setContentText("Are you sure you want to perform this action ?");

    Optional<ButtonType> result = alert.showAndWait();
    if (result.get() == ButtonType.OK) {
     // delete user
 }

result.get() 返回一个布尔值。因此,您可以在 if 条件语句中比较返回值以检查用户是否点击了ButtonType.OKButtonType.CANCEL 按钮。

以下是一个示例,供您理解:

图片描述

默认情况下,Alert 对话框显示两个按钮:确定(OK)和取消(Cancel)。但如果您希望自定义 Alert 对话框,则可以像下面这样添加自己的按钮类型:

ButtonType buttonTypeOne = new ButtonType("One");
ButtonType buttonTypeTwo = new ButtonType("Two");
ButtonType buttonTypeThree = new ButtonType("Three");

将它们添加到警报中:
alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeTwo, buttonTypeThree);

所以您可以检查用户按下了哪个按钮。
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == buttonTypeOne){
    // ... user chose "One"
} else if (result.get() == buttonTypeTwo) {
    // ... user chose "Two"
} else{
    // ... user chose "Three"
}

非常抱歉,我完全不理解这个。这些是JavaFX命令吗?.setContentText,.setHeaderText,.showAndWait()等等?Optional<ButtonType>是什么意思? - Hatefiend
1
@Hatefiend 是的,他正在使用 JavaFX Dialog 类。 - crigore
你如何在不使用Dialog类的情况下实现它?一定有办法可以通过使用自己的类来完成。 - Hatefiend

1
你可以将可变对象(MutableBool 类)作为传递的参数添加。由于可变对象被作为指针传递,你可以分配一个值以在方法外检查它。
添加类:
class MutableBool{
    private boolean value;

    public void setValue(boolean value) {
        this.value = value;
    }

    public boolean getValue() {
        return value;
    }
}

并且对于你的代码进行了一些更改:

public boolean display(String title, String message, MutableBool answer){
    ...
    answer.setValue(true);
}

好的,那么我会这样做:boolean variable = false(假设用户会选择“否”)。AlertBox warning = new AlertBox(); warning.display("警告", "小心!", variable); 然后,在display方法中,如果我改变了variable的值,它也会在我的GUI类中显示?我不知道原始类型是按引用传递的。 - Hatefiend
2
这样行不通。在Java中,布尔类是不可变的。你可以从外部访问实例答案,但不能对其进行更改。如果你在你的类/方法内部给变量答案赋一个新值,那么将使用一个新对象,而你无法从外部访问它(因为你持有旧实例的引用)。你可以使用可变对象来做类似的事情。 - DThought
@DThought,抱歉,我没有考虑到这一点。我改变了答案。 - Axifive
我刚刚在想这个问题。这样的东西怎么能起作用,但是只传递一个布尔值却不行,这真是太奇怪了。这算是糟糕的编程吗? - Hatefiend
你可以这样做,但是你怎么知道用户已经按下了按钮? - Tomasz Mularczyk

1

如果你想使用自己的类,我认为你不能不使用EventHandler。如果你真的想要使用自己的类,可以尝试以下方法:

AlertBox alert = new AlertBox("title","message");
alert.setYesAction( e -> {
    //TO-DO
});
alert.setNoAction( e -> {
    //TO-DO
});
alert.showAndWait();

如果您想检查用户是否按下按钮以取消操作,您可以调用以下代码:alert.isCanceled()

import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.*;

/**
 * An Alert Box for the GUI to display errors to the user.
 *
 */
public class AlertBox extends Stage {
    private boolean cancel = false;
    private EventHandler<ActionEvent> yesAction = null;
    private EventHandler<ActionEvent> noAction = null;

    public AlertBox(String title, String message) {
        super();
        initModality(Modality.APPLICATION_MODAL); // If window is up,
        // make user handle
        // it.
        setTitle(title);
        setMinHeight(350);
        setMinWidth(250);

        VBox root = new VBox(); // Root layout.

        Label warning = new Label(message); // Message explaining what is wrong.

        HBox buttonLayout = new HBox(); // The yes and cancel button.

        Button yesButton = new Button("Yes"); // Yes button for the user.
        Button noButton = new Button("No"); // No button for the user.

        yesButton.setOnAction(e -> {
            cancel = false;
            yesAction.handle(new ActionEvent());
        });

        noButton.setOnAction(e -> {
            cancel = true;
            noAction.handle(new ActionEvent());
        });
        buttonLayout.getChildren().addAll(yesButton, noButton);

        root.getChildren().addAll(warning, buttonLayout);
        root.setAlignment(Pos.CENTER);

        Scene scene = new Scene(root);
        setScene(scene);
    }

    public void setYesAction(EventHandler<ActionEvent> yesAction){
        this.yesAction = yesAction;
    }
    public void setNoAction(EventHandler<ActionEvent> noAction){
        this.noAction = noAction;
    }

    public boolean isCanceled(){
        return cancel;
    }
}

0

或者你可以在主类中处理:

package application;

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;

public class Main extends Application {
    @Override
    public void start(final Stage primaryStage) {
    try {
        final BorderPane root = new BorderPane();
        final Scene scene = new Scene(root, 400, 400);

        final AlertBox warning = new AlertBox("Warning!",
                "You are about to delete your account. Are you sure you  would like to do this?");    

            warning.addCancelListener(new ChangeListener<Boolean>() {

            @Override
            public void changed(final ObservableValue<? extends Boolean> observable, final Boolean oldValue, final Boolean newValue) {
                if (newValue) {
                    System.out.println("Tschüss");
                } else {
                    System.out.println("Thanks for confidence");
                }
            }
        });

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

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

package application;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;

/**
 * An Alert Box for the GUI
 * to display errors to the user.
 */
public class AlertBox {
    Stage window;
    ObjectProperty<Boolean> cancel = new SimpleObjectProperty<>(null);

    public AlertBox(final String title, final String message) {
        cancel.setValue(null);
        display(title, message);
    }

    private void display(final String title, final String message) {
        window = new Stage(); // Create the stage.

        window.initModality(Modality.APPLICATION_MODAL); // If window is up, make user handle it.
        window.setTitle(title);
        window.setMinHeight(350);
        window.setMinWidth(250);
        window.setAlwaysOnTop(true);

        final VBox root = new VBox(); // Root layout.

        final Label warning = new Label(message); // Message explaining  what is wrong.

        final HBox buttonLayout = new HBox(); // The yes and cancel button.

        final Button yesButton = new Button("Yes"); // Yes button for the user.
        final Button noButton = new Button("No"); // No button for the user.

        yesButton.setOnAction(e -> {
            cancel.set(false);
            close();
        });

        noButton.setOnAction(e -> {
            cancel.set(true);
            close();
        });

        buttonLayout.getChildren().addAll(yesButton, noButton);

        root.getChildren().addAll(warning, buttonLayout);
        root.setAlignment(Pos.CENTER);

        final Scene scene = new Scene(root);
        window.setScene(scene);
        window.show();
    }

    /**
     * Closes the window
     *
     * @param variable
     */
    private void close() {
        window.close();
    }

    public void addCancelListener(final ChangeListener<Boolean> listener) {
        cancel.addListener(listener);
    }
}

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