【问题标题】:Don't open Java GUI when opened from a command-line从命令行打开时不要打开 Java GUI
【发布时间】:2018-07-23 16:00:39
【问题描述】:

我正在尝试使用相同的 jar 文件(如果可能)实现以下目标:

  1. 指定命令行参数后,作为 CLI 工具(无 GUI)运行 - 这很简单
  2. 当用户在 Windows 资源管理器中双击 .jar 文件启动应用程序时,或在 Nautilus 中双击启动应用程序时,应启动 GUI
  3. 当用户从控制台/终端(例如cmd.exezshbash)中的shell 启动程序时,应打印使用信息并在执行此操作后退出程序(如运行@ 987654326@ 或程序 --help`),无需打开 GUI。

简单的args.length > 0 不足以完成此任务,因为通过终端(使用java -jar program.jar)启动不带任何命令行参数的启动与通过 Windows 资源管理器或 Nautilus 启动时的处理方式不同。


有没有办法实现所描述的行为,我的程序是否必须检查它的父进程是什么,或者这样的事情根本不可行/不可能?

【问题讨论】:

  • 是什么阻止您添加该选项?
  • minimal reproducible example开头 :) 所以不是论坛或教程点,谢谢
  • 即使那个 C# 问题也给了你指导......
  • @Mickael 我希望我重新编写的问题更有意义。

标签: java swing user-interface command-line command-line-interface


【解决方案1】:

你可能想要这样的东西:

public static void main(String[] args) {
    if (args.length > 0) {
        //use as command line tool
    } else {
        //start GUI
    }
}

你只需要检查是否有命令行参数。

【讨论】:

  • 感谢您的回复,但从 CLI 启动永远不应打开 GUI,而是显示使用信息。仅当从命令行外部启动时,程序才应显示 GUI。对困惑感到抱歉;我编辑了我原来的问题。
  • "但是从 CLI 启动永远不应该打开 GUI" 为什么不呢?您是否尝试过通过终端执行应用程序?如果他们有一个 gui,它将通过输入应用程序名称并使用选项打开,您可以获得其他形式的信息,这些信息可能会或可能不会出现在 GUI 中
【解决方案2】:

OOP、架构、SOLID 原则等等……

在 SOLID 原则中,有第一个原则是Single Responsibility Principle,其中必须将每个责任分离到它自己的对象中,每个对象只有一个责任。因此,不能将应用程序逻辑放在同一个 UI 对象中。

您的解决方案是将应用程序逻辑与 UI 分开,然后制作另一个界面,即命令行界面。

例如:你想做两个数字相加的东西。

一个是 JFrame,有两个 JTextField 和一个按钮。然后你添加 按钮上的单击侦听器,它将两个数字相加并将其打印在 JLabel 上。但是,如果是这样,怎么可能做 CLI 呢?

在这种情况下,你应该做这样的事情,它处理 Swing 和 CLI 之间的公共逻辑(应用程序逻辑):

interface NumberAdditionResultAsString {
    void postResult(String result);
    void postError(Exception ex);
}

class NumberAdderFromStrings {
    void executeTheAddition(String num1, String num2, NumberAdditionResultAsString listener) {
        try {
            double n1 = Double.parseDouble(num1);
            double n2 = Double.parseDouble(num2);
            listener.postResult(Double.toString(n1 + n2));
        } catch(Exception ex) {
            listener.postError(ex);
        }
    }
}

现在可以从 Swing 和 CLI 轻松调用此应用程序逻辑。 还使用了更适合处理发生在其他线程上的冗长操作的“回调”。

另外,如果你想要更复杂的东西,你可以使用command 设计模式。所有这些“应用程序逻辑”都实现了一个接口。然后你的 UI 和 CLI 都会调用它们。

interface ApplicationCommand {
    Object execute(Object... parameters);
}

然后在你的主应用程序类中做类似的事情:

Map<String, ApplicationCommand> commandMap = new HashMap<>();

然后像这样填充它:

commandMap.put("add", new ApplicationCommand() {
    @Override
    public Object execute(Object... parameters) {
        double sum = 0;
        for (Object one: parameters) {
            sum += Double.parseDouble(one.toString());
        }
        return sum;
    }
});

嗯,这不是最好的设计。最好将每个字符串与创建命令的工厂对象相关联,而不是与命令对象本身相关联。但这是为了简单起见。

建议:了解一下

Command design pattern

Strategy design pattern

Abstract factory design pattern

Flyweight design pattern(可以帮助正确创建命令映射)

SOLID Principles(主要阅读:单一职责、依赖倒置)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-30
    • 2013-08-17
    • 1970-01-01
    相关资源
    最近更新 更多