如何防止JFrame关闭

8
我有一个Java GUI应用程序,可以使用反射和加载来调用另一个Java GUI应用程序。它可以正常工作,唯一遇到的问题是,在关闭被调用应用程序的JFrame时,主GUI应用程序框架也会关闭。我该如何防止主应用程序(框架)关闭??
我无法更改被调用应用程序的defaultCloseOperation,但可以对主应用程序进行更改。这是否与线程有关?
以下是我的应用程序代码,用于执行目标应用程序:
public class ClassExecutor{

    private ClassLoaderOfExtClass classLoader;
    private byte[][] ArrayOfClasses;
    private String[] ArrayOfBinaryNames;
    @SuppressWarnings("rawtypes")
    private ArrayList<Class> loadedClasses;
    private ArrayList<String> loadedClasesNames;
    private Object[] parameters;


    @SuppressWarnings("rawtypes")
    public ClassExecutor() {
        classLoader = new ClassLoaderOfExtClass();
        new ArrayList<Class>();
        loadedClasses = new ArrayList<Class>();
        loadedClasesNames = new ArrayList<String>();
    }

    @SuppressWarnings("unchecked")
    public void execute(File[] file, String[] binaryPaths) {
        Object[] actuals = { new String[] { "" } };
        Method m = null;
        try {
            Field classesx=ClassLoaderOfExtClass.class.getDeclaredField("classes");
            classesx.setAccessible(true);
        } catch (SecurityException e1) {
            e1.printStackTrace();
        } catch (NoSuchFieldException e1) { 
            e1.printStackTrace();
        }


        /*for (int i = 0; i < file.length; i++) {
            for (int j = 0; j < file.length; j++) {

                try {

                    @SuppressWarnings("rawtypes")
                    Class c = classLoader.loadClassCustom(file[i], binaryPaths[i]);
                //Fied classex=classLoader.getResource("classes");
                }catch(Exception e){

                }

            }
        }
        Class<?>[]classesxx= getLoadedClasses(classLoader);
        System.out.println("Loaded classes have size "+ classesxx.length);*/

        for (int i = 0; i < file.length; i++) {
            try {
                @SuppressWarnings("rawtypes")
                Class c = classLoader.loadClassCustom(file[i], binaryPaths[i]);

                try {
                    if (c.getMethod("main", new Class[] { String[].class }) != null) {
                        m = c.getMethod("main", new Class[] { String[].class });
                    } else {

                        System.out.println("This class does not contain main");
                        continue;
                    }

                } catch (NoSuchMethodException e) {
                //  System.out.println("Main not found!!!");
                    // System.out.println("M here");
                    // e.printStackTrace(); // not printing stack trace
                } catch (SecurityException e) {
                    e.printStackTrace();
                }

            } catch (ClassNotFoundException e) {
                System.out.println("No such class definition exist!!");
                // TODO Auto-generated catch block
                // e.printStackTrace();
            }

        }

        try {

            m.invoke(null, actuals);

            // CallStack.print();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public void execute(ArrayList<byte[]> stuffedFiles,
            ArrayList<String> binaryPaths) {
        convertToArray(stuffedFiles, binaryPaths);
        loadAllClasses(ArrayOfClasses, ArrayOfBinaryNames);
        Object[] actuals = { new String[] { "" } };
        Method m = null;

        /*
         * Method[] m1= new Method[10]; for (Class c : loadedClasses) {
         * m1=c.getMethods(); } for(Method m2: m1){
         * System.out.println(m2.getName()); }
         */
        /* System.out.println(loadedClasses.size()); */
        for (Class c : loadedClasses) {
            /*
             * System.out.println(c.toString());
             * System.out.println(c.getConstructors());
             */
            // for (int i = 1; i < file.size(); i++) {
            /*
             * for(Method meth : c.getMethods()){ meth.setAccessible(true);
             * 
             * }
             */

            try {
                if (c.getMethod("main", new Class[] { String[].class }) != null) {
                    m = c.getMethod("main", new Class[] { String[].class });
                    break;
                } else {

                //  System.out.println("This class does not contain main");
                    continue;
                }

            } catch (NoSuchMethodException e) {

                System.out.println("Program does not contain main");

            } catch (SecurityException e) {
                e.printStackTrace();
            }

        }

        try {

            if(parameters==null){

            m.invoke(null, actuals);
            }
            else{
                try {

                    System.out.println("It Fails Here");
                    m.invoke(null, parameters);
                } catch (Exception e) {
                    System.out.println("Illegal arguments");
                }
            }

            // CallStack.print();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

@Spaeth,正如我所提到的,我无法访问被调用应用程序的defaultCloseOperation。 - Sanyam Goel
@Spaeth 如果这个图可以帮助你理解我的问题,请告诉我,否则我会发布代码,因为它们非常冗长。 - Sanyam Goel
好的,现在我明白你的问题了,你调用了main函数对吧? - Francisco Spaeth
@Spaeth 是的,现在问题出现了,当我关闭目标应用程序时,我的应用程序也会关闭 :( - Sanyam Goel
我明白了,也许你可以在调用应用程序之前获取窗口,然后在调用它之后再次获取窗口,并检查窗口列表中的新内容,将新的设置为关闭操作。 - Francisco Spaeth
显示剩余8条评论
3个回答

11

你需要使用DISPOSE_ON_CLOSE操作,这样你就可以设置setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE)

EXIT_ON_CLOSE是关闭所有窗口的选项,我相信这可能是你当前正在遇到的问题。


是的,你说得对,所有的窗口都在关闭,你的理由似乎是正确的。然而,我无法访问被调用应用程序的源代码,因此无法更改其默认的关闭操作。 - Sanyam Goel
如果您正在使用反射调用应用程序,那么为什么不能在此过程中使用反射设置默认的关闭操作呢? - Roddy of the Frozen Peas
@RoddyoftheFrozenPeas 我不被允许对被调用的应用做出更改。我能改变的只有我的代码。 - Sanyam Goel

6
您可以在defaultCloseOperation中选择以下选项:
  • DO_NOTHING_ON_CLOSE - 无操作默认窗口关闭操作;
  • HIDE_ON_CLOSE - 默认窗口关闭操作为隐藏窗口;
  • DISPOSE_ON_CLOSE - 默认窗口关闭操作仅关闭所需的窗口而不关闭所有窗口。
  • EXIT_ON_CLOSE - 退出应用程序默认窗口关闭操作. 如果在支持此操作的Windows上(如JFrame), 尝试设置此操作可能会根据安全管理器抛出SecurityException。建议您只在应用程序中使用此操作。

选项DISPOSE_ON_CLOSE可用于避免关闭所有窗口,仅关闭您想要关闭的窗口。

如果您没有像最后发布的代码一样直接访问JFrame对象,则可以使用Window.getWindows()来接收所有窗口实例(因为JFrame也是一个Window,所以它也会被列出)。然后在其上设置defaultCloseOperation

可能需要使用线程,因为defaultCloseOperation需要在调用主方法后设置。

理论上它可以工作,所以我认为这是一个好尝试;)


不,这并不能解决我的问题。调用应用程序有自己的JFrame,必须防止在关闭被调用应用程序的JFrame时关闭它。 - Sanyam Goel

3
这是对@JeffLaJoie的回复,明确指出不允许更改被调用应用程序的代码。只需在运行时通过额外的方法调用或两个方法调用,在您的应用程序中设置第三方框架的关闭操作即可,无需对其他应用程序的代码进行任何更改。
如果无法实现上述方法,则我能想到的最好解决方案是启动一个新的Process,并在其中启动一个新的JVM来打开新的框架。当用户关闭其他应用程序时,它和第二个JVM将会结束,而原始应用程序将保持在屏幕上。

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