Java 如何防止JFrame关闭但仍不工作

Java 如何防止JFrame关闭但仍不工作,java,swing,reflection,jframe,Java,Swing,Reflection,Jframe,我正在测试这个问题的解决方案 我遇到的问题是,如果我尝试调用一个应用程序,例如,该解决方案将不起作用。因此,在调用Applic2main之后,不只是添加以下代码 Frame[] f2 = JFrame.getFrames(); for(Frame fx: f2){ if (fx instanceof JFrame) { JFrame aFrame = (JFrame)fx;

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

我遇到的问题是,如果我尝试调用一个应用程序,例如,该解决方案将不起作用。因此,在调用
Applic2
main之后,不只是添加以下代码

        Frame[] f2 = JFrame.getFrames();
        for(Frame fx: f2){


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

                  aFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

              }
            }
我创建了一个异步线程,它不断地将JFrame.EXIT\u on\u操作更改为JFrame.DISPOSE\u on\u 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方法调用该线程实例。但解决方案并不奏效。但我仍然面临着同样的问题,所有的帧都在一帧上关闭。为什么会发生这种情况?有什么建议以及如何克服这种情况

请检查以下问题:

让我更详细地介绍这个问题

将代码添加到工作区

将以下包添加到房地产代码中

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包的主要部分,哪个inturn调用RealEstate游戏。这就是解决方案不起作用的地方,尝试关闭不同的不动产框架,然后看到整个应用程序关闭。

因此,我已经做了一个快速测试,我可以让它正常工作

首先,我创建了三个JFrames(都是相同的,因为我很匆忙),其中默认的关闭值设置为
EXIT\u ON\u close

我验证了如果我关闭一个,它将关闭所有三个

然后我使用
javax.swing.Timer
在可用帧列表中重复循环,并将默认关闭值设置为
DISPOSE\u ON\u close

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

一旦执行,我就能够监视以下输出

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”,并一直保持这种状态,直到我厌倦了输出并终止程序

我还检查了关闭一个或多个帧是否会退出程序


现在,有一个重要的提示。我相信这只适用于已经实现的帧(在屏幕上可见),但您可以测试这一点,看看您得到了什么;)

我快速检查了房地产游戏的代码,在
MainWindow.java中发现了您的问题:

this.addWindowListener(new WindowAdapter(){
    public void windowClosing(WindowEvent e) {
        System.exit(0);
    }
});
如果您仍然希望窗口关闭,我不确定您可以从外部对此做些什么。

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

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;
  }
}

请注意,不要从ETD以外的任何线程修改Swing组件,当我们考虑您的问题时,请阅读Swing中的并发性此解决方案不适用于房地产问题:(正如前面的链接中所提到的,为什么会发生这种情况?是因为房地产游戏的框架对象不可访问或无法锁定???+1以查找它:-)至于如何处理它:如果有对该窗口的引用,请删除侦听器(通过window.getWindowListener()循环)并删除同名上下文中的匿名,类似于MainWindow$
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;
  }
}