如何防止JFrame关闭仍然无法正常工作

时间:2012-07-23 10:06:56

标签: java swing reflection jframe

我正在测试问题的解决方案

Will new instance of JVM or reflection help in this case

我遇到的是,如果我尝试调用Real Estate game等应用程序,则此解决方案不起作用。因此,在调用Applic2

的主要内容后,只需添加以下代码即可
        Frame[] f2 = JFrame.getFrames();
        for(Frame fx: f2){


              if (fx instanceof JFrame) {
                  JFrame aFrame = (JFrame)fx;

                  aFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

              }
            }

我创建了一个异步线程,不断将操作JFrame.EXIT_ON_CLOSE更改为JFrame.DISPOSE_ON_CLOSE,如下所示

import java.awt.Frame;

import javax.swing.JFrame;

public class FrameMonitor extends Thread{

    @Override
    public void run(){

        while(true){
            Frame[] f2 = JFrame.getFrames();

            for(Frame fx : f2){

                if(fx instanceof JFrame){
                    JFrame aframe =(JFrame)fx;
                    aframe.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                }
            }
        }
    }
}

并通过MyApp类中的start方法调用此线程实例。但解决方案无效。我仍然面临关闭一帧时所有帧关闭的相同问题。为什么会发生任何建议以及如何克服这个?

请完成以下问题:

让我更详细地介绍问题

Real Estate game代码添加到工作区

将以下包添加到RealEstate代码

package MyApplication;

import java.awt.Frame;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.swing.JFrame;

import edu.ncsu.realestate.gui.Main;

public class MYApp {

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static void main(String arg[]){

        FrameMonitor monitor = new FrameMonitor();
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(200,200);
        f.setVisible(true);
        Class cls = Main.class;
        Object[] actuals = { new String[] {} };
    //  cls.
        Method[] mts=cls.getMethods();
        for(Method m : mts){
            //System.out.println(m);
        }
        Method m = null;
        try {
            m=cls.getMethod("main", new Class[] { String[].class } );
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
            try {
                m.invoke(null,actuals);
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            Frame[] f2 = JFrame.getFrames();
            for(Frame fx: f2){
                System.out.println(fx.getTitle());
                //  fx.setVisible(false);

                  if (fx instanceof JFrame) {
                     // System.out.println("M here");
                    //  System.out.println(fx.getTitle());
                      System.out.println(fx.getName());
                      JFrame aFrame = (JFrame)fx;

                      aFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

                  }
                }

    }


}



package MyApplication;

import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.Timer;

public class FrameMonitor{

    public FrameMonitor(){
    Timer timer = new Timer(10000, new FrameMonitor2());
    timer.setCoalesce(true);
    timer.setRepeats(true);
    timer.start();

}


    public static class FrameMonitor2 implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent ae) {

            Frame[] frames = Frame.getFrames();
            for (Frame frame : frames) {

                if (frame instanceof JFrame) {

                    JFrame change = (JFrame) frame;
                    System.out.println("Before = " + change.getTitle() + " = " + change.getDefaultCloseOperation());
                    ((JFrame)frame).setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                    System.out.println("After = " + change.getTitle() + " = " + change.getDefaultCloseOperation());

                }

            }

        }


    }

}

现在调用MyApplication包的主要部分,然后调用RealEstate游戏。这是解决方案不起作用的地方,尝试关闭不同的RealEstate帧并查看整个应用程序关闭。

3 个答案:

答案 0 :(得分:5)

我快速检查了房地产游戏的代码,并在MainWindow.java中找到了问题:

this.addWindowListener(new WindowAdapter(){
    public void windowClosing(WindowEvent e) {
        System.exit(0);
    }
});

我不确定如果你仍然希望窗户关闭,你可以从外面做什么,如果有的话。

答案 1 :(得分:2)

所以,我做了一个快速测试,我可以让它工作正常。

首先,我创建了三个JFrame(所有相同的原因我都很匆忙),默认关闭值设置为EXIT_ON_CLOSE

我确认如果我关闭了一个,它就会关闭所有三个。

然后,我使用javax.swing.Timer重复循环显示可用框架列表,并将默认关闭值设置为DISPOSE_ON_CLOSE

Timer timer = new Timer(1000, new UpdateTask());
timer.setCoalesce(true);
timer.setRepeats(true);
timer.start();

...

public static class UpdateTask implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent ae) {

        Frame[] frames = Frame.getFrames();
        for (Frame frame : frames) {

            if (frame instanceof JFrame) {

                JFrame change = (JFrame) frame;
                System.out.println("Before = " + change.getTitle() + " = " + change.getDefaultCloseOperation());
                ((JFrame)frame).setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                System.out.println("After = " + change.getTitle() + " = " + change.getDefaultCloseOperation());

            }

        }

    }

}

执行后,我能够监控以下输出

Before = Frame 01 = 3
After = Frame 01 = 2
Before = Frame 02 = 3
After = Frame 02 = 2
Before = Frame 03 = 3
After = Frame 03 = 2
Before = Frame 01 = 2
After = Frame 01 = 2
Before = Frame 02 = 2
After = Frame 02 = 2
Before = Frame 03 = 2
After = Frame 03 = 2

如你所见。在第一次迭代中,帧从“3”变为“2”并保持这种状态,直到我厌倦输出并终止程序。

我还检查过关闭一个或多个框架 NOT 退出程序。

现在,一个重要的注意事项。我相信这只适用于已经实现的帧(在屏幕上可见),但是你可以测试它并看看你得到了什么;)

答案 2 :(得分:1)

一种方式(不一定是最好的)是实现自定义安全管理器。

import java.awt.*;
import java.awt.event.*;
import java.security.Permission;

/** NoExit demonstrates how to prevent 'child'
applications from ending the VM with a call
to System.exit(0).
@author Andrew Thompson */
public class NoExit extends Frame implements ActionListener {

  Button frameLaunch = new Button("Frame"),
     exitLaunch = new Button("Exit");

  /** Stores a reference to the original security manager. */
  ExitManager sm;

  public NoExit() {
     super("Launcher Application");

     sm = new ExitManager( System.getSecurityManager() );
     System.setSecurityManager(sm);

     setLayout(new GridLayout(0,1));

     frameLaunch.addActionListener(this);
     exitLaunch.addActionListener(this);

     add( frameLaunch );
     add( exitLaunch );

     pack();
     setSize( getPreferredSize() );
  }

  public void actionPerformed(ActionEvent ae) {
     if ( ae.getSource()==frameLaunch ) {
        TargetFrame tf = new TargetFrame();
     } else {
        // change back to the standard SM that allows exit.
        System.setSecurityManager(
           sm.getOriginalSecurityManager() );
        // exit the VM when *we* want
        System.exit(0);
     }
  }

  public static void main(String[] args) {
     NoExit ne = new NoExit();
     ne.setVisible(true);
  }
}

/** This example frame attempts to System.exit(0)
on closing, we must prevent it from doing so. */
class TargetFrame extends Frame {
  static int x=0, y=0;

  TargetFrame() {
     super("Close Me!");
     add(new Label("Hi!"));

     addWindowListener( new WindowAdapter() {
        public void windowClosing(WindowEvent we) {
           System.out.println("Bye!");
           System.exit(0);
        }
     });

     pack();
     setSize( getPreferredSize() );
     setLocation(++x*10,++y*10);
     setVisible(true);
  }
}

/** Our custom ExitManager does not allow the VM
to exit, but does allow itself to be replaced by
the original security manager.
@author Andrew Thompson */
class ExitManager extends SecurityManager {

  SecurityManager original;

  ExitManager(SecurityManager original) {
     this.original = original;
  }

  /** Deny permission to exit the VM. */
   public void checkExit(int status) {
     throw( new SecurityException() );
  }

  /** Allow this security manager to be replaced,
  if fact, allow pretty much everything. */
  public void checkPermission(Permission perm) {
  }

  public SecurityManager getOriginalSecurityManager() {
     return original;
  }
}