为什么ControlsFX对话框被弃用?

21

ControlsFX类Dialogs被标记为不建议使用。

应该使用什么替代方案?

2个回答

16

现在随着Java 8更新60,即使使用旧的未弃用版本的controlsfx也无法工作。所以,解决方案是使用Java 8更新40中包含的JavaFX本机对话框API(不需要第三方库)。它们不像ControlsFX那样直截了当且功能丰富。但为了更快的编码,您可以创建一个包装器类,就像我制作的这个:

package br.atualy.devolucaodevenda.util;

import javafx.scene.control.*;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.stage.StageStyle;

import java.awt.*;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class FxDialogs {

    public static void showInformation(String title, String message) {
        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        alert.initStyle(StageStyle.UTILITY);
        alert.setTitle("Information");
        alert.setHeaderText(title);
        alert.setContentText(message);

        alert.showAndWait();
    }

    public static void showWarning(String title, String message) {
        Alert alert = new Alert(Alert.AlertType.WARNING);
        alert.initStyle(StageStyle.UTILITY);
        alert.setTitle("Warning");
        alert.setHeaderText(title);
        alert.setContentText(message);

        alert.showAndWait();
    }

    public static void showError(String title, String message) {
        Alert alert = new Alert(Alert.AlertType.ERROR);
        alert.initStyle(StageStyle.UTILITY);
        alert.setTitle("Error");
        alert.setHeaderText(title);
        alert.setContentText(message);

        alert.showAndWait();
    }

    public static void showException(String title, String message, Exception exception) {
        Alert alert = new Alert(Alert.AlertType.ERROR);
        alert.initStyle(StageStyle.UTILITY);
        alert.setTitle("Exception");
        alert.setHeaderText(title);
        alert.setContentText(message);

        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        exception.printStackTrace(pw);
        String exceptionText = sw.toString();

        Label label = new Label("Details:");

        TextArea textArea = new TextArea(exceptionText);
        textArea.setEditable(false);
        textArea.setWrapText(true);

        textArea.setMaxWidth(Double.MAX_VALUE);
        textArea.setMaxHeight(Double.MAX_VALUE);
        GridPane.setVgrow(textArea, Priority.ALWAYS);
        GridPane.setHgrow(textArea, Priority.ALWAYS);

        GridPane expContent = new GridPane();
        expContent.setMaxWidth(Double.MAX_VALUE);
        expContent.add(label, 0, 0);
        expContent.add(textArea, 0, 1);

        alert.getDialogPane().setExpandableContent(expContent);

        alert.showAndWait();
    }

    public static final String YES = "Yes";
    public static final String NO = "No";
    public static final String OK = "OK";
    public static final String CANCEL = "Cancel";

    public static String showConfirm(String title, String message, String... options) {
        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
        alert.initStyle(StageStyle.UTILITY);
        alert.setTitle("Choose an option");
        alert.setHeaderText(title);
        alert.setContentText(message);

        //To make enter key press the actual focused button, not the first one. Just like pressing "space".
        alert.getDialogPane().addEventFilter(KeyEvent.KEY_PRESSED, event -> {
            if (event.getCode().equals(KeyCode.ENTER)) {
                event.consume();
                try {
                    Robot r = new Robot();
                    r.keyPress(java.awt.event.KeyEvent.VK_SPACE);
                    r.keyRelease(java.awt.event.KeyEvent.VK_SPACE);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        if (options == null || options.length == 0) {
            options = new String[]{OK, CANCEL};
        }

        List<ButtonType> buttons = new ArrayList<>();
        for (String option : options) {
            buttons.add(new ButtonType(option));
        }

        alert.getButtonTypes().setAll(buttons);

        Optional<ButtonType> result = alert.showAndWait();
        if (!result.isPresent()) {
            return CANCEL;
        } else {
            return result.get().getText();
        }
    }

    public static String showTextInput(String title, String message, String defaultValue) {
        TextInputDialog dialog = new TextInputDialog(defaultValue);
        dialog.initStyle(StageStyle.UTILITY);
        dialog.setTitle("Input");
        dialog.setHeaderText(title);
        dialog.setContentText(message);

        Optional<String> result = dialog.showAndWait();
        if (result.isPresent()) {
            return result.get();
        } else {
            return null;
        }

    }

}

使用对话框:

FxDialogs.showInformation("Hi", "Good Morning y'all!");
if (FxDialogs.showConfirm("Choose one baby!", "Can i ask you a question?", FxDialogs.YES, FxDialogs.NO).equals(FxDialogs.YES)) {
    FxDialogs.showWarning(null, "Pay attention to my next question!");
    String answer = FxDialogs.showTextInput("Are you a pink elephant disguised as a flying pig?", "Tell me!", "No");
    FxDialogs.showError(null, "You should not have said " + answer + "!");
    FxDialogs.showException("Now i'm angry", "I'm going home...", new RuntimeException("Exception caused by angry dinossaurs"));
}

你看过并尝试过这个吗?“对于JavaFX 8u60及更高版本的用户,请下载ControlsFX 8.40.10-SNAPSHOT构建。” - mipa
较新的版本(至少一段时间以前)已经弃用了Dialogs类,这个版本修复了吗? 我在maven上找不到那个版本,最后一个是maven中央库的8.40.9版本。虽然我可以找到该jar文件,但我需要在本地存储库上手动安装它吗? - Mateus Viccari
正如文件名所示,这是一个快照版本,因此您不太可能在Maven中心找到它。因此,您必须以某种方式手动安装它。我不知道更改是什么,但至少对于8u60似乎是必要的,否则他们不会在其网站上提到它。 - mipa

15
这篇博客文章讲解了所有内容:

http://fxexperience.com/2014/09/announcing-controlsfx-8-20-7/

自从5月29日发布8.0.6版本以来,这个版本一直在酝酿中,基本上持续了四个月。这对我们来说并不典型(通常我们发布速度更快),但是 Eugene 和我都被一个重大任务分心了 - 将 ControlsFX 对话框 API 和实现提升到 JavaFX 的下一个版本中(它将出现在 JavaFX 8u40 中,尽管该 API 与 ControlsFX 8.0.6 中所看到的完全不同)。最终结果是,我们通过了一堆 API 设计工作(请参见 RT-12643),但没有一个受益于 ControlsFX,而且这占据了我们所有的时间。

一旦 JavaFX 8u40 对话框完成了 API(仅在8月中旬),我们就制定了一个计划,以便如何处理 ControlsFX 对话框。实际上,我们认为在 ControlsFX 中维护与 JavaFX 8u40 不同的对话框 API 是不明智的。因此,我们制定的计划是弃用旧的 ControlsFX API,将 JavaFX 对话框 API fork 成一个名为 openjfx-dialogs 的新项目,并使用新 API 重新创建 ControlsFX 包括的其他功能(但在 JavaFX 自身中缺少的功能),其中包括进度对话框、字体选择器、命令链接、登录等对话框。


3
谢谢你提供的链接。控制FX做出了一个很糟糕的决定。新库是GPL协议,不能在大多数应用程序中使用。因此,这两个API有不同的重点,旧API真的不应该被弃用... - Marc von Renteln
2
根据 https://bitbucket.org/controlsfx/openjfx-dialogs ,许可证是GPL加上Classpath-Exception,这意味着它可以在商业应用中使用。(免责声明:我不是律师) - rli
@ArtjomB。是的,但是您的评论是在编辑成可行答案之前的3个月。好吧,现在已经解决了,答案很好,这是最终目标。 - James

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