简体   繁体   English

如何在不杀死 JVM 的情况下停止 Java GUI

[英]How to stop Java GUI without killing the JVM

I have a java console application that opens a GUI application that is on a separate class after the user gives a certain input.我有一个 java 控制台应用程序,它在用户提供特定输入后打开一个位于单独 class 上的 GUI 应用程序。 I want to return back to the console once I close the GUI which is achieved by pressing an "Exit" button that the user has the option to do another task or repeat it.我想在关闭 GUI 后返回控制台,这是通过按下“退出”按钮实现的,用户可以选择执行另一项任务或重复它。 I noticed that killing the system with System.exit(0) kills the whole process.我注意到用System.exit(0)杀死系统会杀死整个过程。 I tried working things with threads but I'm relatively new to this and it doesn't seem to work either.我尝试使用线程来处理事情,但我对此比较陌生,而且它似乎也不起作用。 Can someone point me in the right direction?有人可以指出我正确的方向吗? Thanks.谢谢。

I tried using frame.dispose() as well.我也尝试使用frame.dispose() It does load up the console and prints out the things as expected on calling the main method on System, but won't allow me to enter another input.它确实会加载控制台并在调用 System 上的 main 方法时按预期打印出内容,但不允许我输入另一个输入。

btnExit.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent e) {
     frame.dispose();
     System.main(null);
 }
});

Error message: Exception in thread "AWT-EventQueue-0" java.util.NoSuchElementException: No line found.错误消息: Exception in thread "AWT-EventQueue-0" java.util.NoSuchElementException: No line found.

Don't call your main method from a listener method.不要从侦听器方法调用您的main方法。 This may look like having the desired effect, but will have the main method running on the event handling thread while the methods invoked for the current event processing are still on the stack.这可能看起来具有预期的效果,但main方法将在事件处理线程上运行,而为当前事件处理调用的方法仍在堆栈上。 This will not only keep their resources in memory, it will backfire if you ever try to open a GUI again.这不仅会将他们的资源保留在 memory 中,如果您再次尝试打开 GUI,它会适得其反。

Further take care not to close any console related resource ( System.in or System.out ) when opening the GUI, as you can't re-open them when you want to use the console again.进一步注意在打开 GUI 时不要关闭任何与控制台相关的资源( System.inSystem.out ),因为当您想再次使用控制台时无法重新打开它们。

If I understand you correctly, you have a program flow in your main method that doesn't follow the event driven flow of a GUI application and you want to return to that program flow.如果我对您的理解正确,您的 main 方法中有一个程序流,它不遵循 GUI 应用程序的事件驱动流,并且您希望返回该程序流。 One approach for a simple GUI, is to use a modal dialog instead of a window or frame.简单 GUI 的一种方法是使用模式对话框而不是 window 或框架。

public static void main(String[] args) {
    // a simple console application
    for(boolean exit = false; !exit; ) {
        System.out.println("Enter choice:");
        System.out.println("\t1 - Say hello");
        System.out.println("\t2 - Open GUI");
        System.out.println("\t3 - Exit");
        switch(System.console().readLine()) {
            case "1": sayHello(); break;
            case "2": openGUI(); break;
            case "3": exit = true; break;
            default: System.out.println("Not a valid input");
        }
    }
}

private static void sayHello() {
    String name = System.console().readLine("Enter your name: ");
    System.out.println("Hello "+name);
}

private static void openGUI() { // a temporary GUI application
    JDialog d = new JDialog((Window)null, Dialog.ModalityType.TOOLKIT_MODAL);
    JButton b = new JButton("Exit GUI");
    b.addActionListener(ev -> d.dispose());
    d.getContentPane().add(b, BorderLayout.PAGE_END);
    d.pack();
    d.setVisible(true);
}

For a modal dialog, the method invocation that will open it does not return until it has been closed.对于模态对话框,将打开它的方法调用在它关闭之前不会返回。 The example uses dispose() to ensure that the resources are released timely and the event handling thread will terminate, so the main method can terminate the program by simply returning, like an ordinary console application.示例使用dispose()来保证资源及时释放,事件处理线程会终止,因此 main 方法可以像普通的控制台应用程序一样简单地返回即可终止程序。

If a dialog is not an option or a more complex GUI is involved, the logic of letting a GUI run until a certain event will happen, has been generalized with the SecondaryLoop class:如果对话框不是一个选项或涉及更复杂的 GUI,则让 GUI 运行直到某个事件发生的逻辑已通过SecondaryLoop class 进行了概括:

public static void main(String[] args) {
    for(boolean exit = false; !exit; ) {
        System.out.println("Enter choice:");
        System.out.println("\t1 - Say hello");
        System.out.println("\t2 - Open GUI");
        System.out.println("\t3 - Exit");
        switch(System.console().readLine()) {
            case "1": sayHello(); break;
            case "2": openGUI(); break;
            case "3": exit = true; break;
            default: System.out.println("Not a valid input");
        }
    }
}

private static void sayHello() {
    String name = System.console().readLine("Enter your name: ");
    System.out.println("Hello "+name);
}

private static void openGUI() {
    JFrame d = new JFrame();
    SecondaryLoop eventLoop = d.getToolkit().getSystemEventQueue().createSecondaryLoop();
    JButton b = new JButton("Exit GUI");
    b.addActionListener(ev -> {
        d.dispose();
        eventLoop.exit();
    });
    d.getContentPane().add(b, BorderLayout.PAGE_END);
    d.pack();
    d.setVisible(true);
    System.out.println("UI created");
    eventLoop.enter();
    System.out.println("UI disposed");
}

Since opening the JFrame does not let the main thread wait, as indicated by the subsequent print statement, this code uses the SecondaryLoop 's enter() method, to enter an event processing loop that will only end when the button's action listener will call the exit() method.由于打开JFrame不会让主线程等待,如后面的 print 语句所示,这段代码使用了SecondaryLoopenter()方法,进入了一个事件处理循环,只有当按钮的动作监听器调用exit()方法。 Then, the main thread returns and continues processing the console loop.然后,主线程返回并继续处理控制台循环。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM