-2

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

在这种情况下,新的 JVM 实例或反射是否有帮助

我遇到的是,如果我尝试调用Real Estate game等应用程序,此解决方案将不起作用。因此,在调用 main 之后,只需添加以下代码 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 方法调用此线程实例。但解决方案不起作用。我仍然面临着关闭一帧时所有帧关闭的相同问题。为什么会发生任何建议以及如何克服这个问题?

请解决以下问题:

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

房地产游戏代码添加到工作区

将以下包添加到 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 包的 main,然后调用 RealEstate 游戏。这是解决方案不起作用的地方,尝试关闭不同的 RealEstate 框架并查看整个应用程序关闭。

4

3 回答 3

5

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

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

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

于 2012-07-23T12:22:05.037 回答
2

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

首先,我创建了三个 JFrames(都是一样的,因为我很匆忙),默认关闭值设置为EXIT_ON_CLOSE.

我证实如果我关闭一个,它将关闭所有三个。

然后我使用 ajavax.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”并保持这种状态,直到我厌倦了输出并终止程序。

我还检查了关闭一个或多个框架不会退出程序。

现在,一个重要的注意事项。我相信这仅适用于已实现的帧(在屏幕上可见),但您可以对此进行测试,看看您得到了什么;)

于 2012-07-23T10:59:44.757 回答
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;
  }
}
于 2012-07-24T00:03:27.157 回答