【问题标题】:Kill JFrame thread in Java on windowClosing event在 windowClosing 事件中杀死 Java 中的 JFrame 线程
【发布时间】:2013-05-16 03:28:46
【问题描述】:

我正在尝试编写应用程序,该应用程序将在按下按钮时创建新窗口,显示当前窗口计数并在关闭窗口时关闭窗口和线程。

所以基本上,功能是这样的(其中一些正在工作):

  1. 启动应用程序时显示窗口(确定)
  2. 按下按钮 (OK) 时创建新窗口
  3. 按下按钮时显示当前窗口计数(创建时确定,关闭窗口时确定)
  4. 按下“X”时销毁窗口(确定)
  5. 关闭原始窗口时销毁主线程 (NOK)

这是我的代码:

package projectpackage;

import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
import java.awt.*;
import java.awt.event.*;

class MyMouseEvent extends MouseAdapter 
{ 
    public void mousePressed(MouseEvent me)
    { 
      MyWindowThread.incrementMyWindowThreadCount();

      MyWindowThread obj1 = new MyWindowThread();

      Thread thr1 = new Thread(obj1); 

      thr1.start();

    }
}

class MyWindowThread extends JFrame implements Runnable
{

  private int height;
  private int width;

  private static int MyWindowThreadCount = 1;

  public static int getMyWindowThreadCount()
  {
    return MyWindowThreadCount;
  }

  public static void incrementMyWindowThreadCount()
  {
    MyWindowThreadCount++;
  }

  public static void decrementMyWindowThreadCount()
  {
    MyWindowThreadCount--;
  }

  public MyWindowThread()
  {
    super("Frame "+getMyWindowThreadCount());

    this.setHeight(300);

    this.setWidth(400);

    this.setBounds(100,100,getWidth(),getHeight());

    this.addWindowListener(new WindowAdapter()
                            {
                             @Override
                             public void windowClosing(WindowEvent e)
                             {
                                MyWindowThread.decrementMyWindowThreadCount();
                                //Thread.currentThread().interrupt(); 
                                return; 
                             }
                            }
                            );

    JPanel panel1 = new JPanel();

    JButton button1 = new JButton("New window");

    JButton button2 = new JButton("Count running windows");

    this.getContentPane().add(panel1);

    panel1.add(button1);

    panel1.add(button2);

    button1.addMouseListener(new MyMouseEvent());

    button2.addMouseListener(new MouseAdapter()
                             {
                               public void mousePressed(MouseEvent me)
                               {
                                 javax.swing.JOptionPane.showMessageDialog(null,"Window count = " + MyWindowThread.getMyWindowThreadCount());
                               }
                             }
                            );

    this.setVisible(true); // show frame
  }

  public int getHeight()
  {
   return this.height;
  }

  public void setHeight(int h)
  {
   this.height = h;
  }

  public int getWidth()
  {
   return this.width;
  }

  public void setWidth(int w)
  {
   this.width = w;
  }

  public void run()
  {

  }

}

public class MyApp 
{

  public static void main(String[] args)
  {
    // Creating objects START

    MyWindowThread obj1 = new MyWindowThread(); 

    Thread thr1 = new Thread(obj1); 

    thr1.start();
  }

}

清单.mf:

清单版本:1.0 主类:projectpackage.MyApp

我希望您知道如何在控制台中编译和运行 Java 应用程序。如果你不这样做,这里是:

(在 CLI 中导航到包含“projectpackage”目录的目录。*.java 文件必须在“projectpackage”目录中)

javac 项目包\*.java jar cfm MyApp.jar manifest.mf projectpackage\* java -jar MyApp.jar

谁能告诉我我做错了什么或者我需要做什么才能使代码正常工作?还是我只是有基本的误解?

【问题讨论】:

  • 请说明此代码的原因,目标是什么
  • mKorbel,目标是用线程控制 JFrame 等 Swing 组件。这是教育应用程序。
  • Swing 的约定是它是单线程的,所有的 Swing 组件都应该被 EDT 访问,而不是其他线程,所以这个练习看起来没什么用。

标签: java multithreading swing jframe terminate


【解决方案1】:
JFrame frame = new JFrame();

这是您的问题,您扩展了 JFrame 类但尝试使用新对象。 如果需要,您应该将此行替换为 super();super("Frame " + getMyThreadCount());

编辑:另一个需要提及的问题:你将你的类命名为 MyThread,这是一个非常烦人的窗口类名;)

编辑 2:其他几件事:

  • public void run()没有内容,为什么MyThread实现Runnable
  • 您创建了一些线程,但如果我没看错,您就不要启动任何线程。

【讨论】:

  • "public void run()没有内容,MyThread为什么要实现Runnable?" - 我只是想熟悉 Java 中的线程,我的代码工作正常(嗯,工作了一半),所以我保持原样。 “你创建了一些线程,但如果我做对了,你就不会启动任何线程。” - 你的意思是我需要在类中添加 MyMouseEvent 方法 mousePressed 行“thr1.start();” ? “你将你的类命名为 MyThread,这是一个非常令人讨厌的窗口类名 ;)” - 将其重命名为“MyWindowThread”
  • 我添加了 thr1.start();在 main() 和 mousePressed() 方法中,更改了“JFrame frame = new JFrame();”到“超级(“帧”+ getMyThreadCount());“和“frame.addWindowListener();”到“this.addWindowListener();” -> 现在当我添加窗口时,添加窗口是可以的,尽管它们都带有标题“Frame 1”,尽管按下按钮“计数窗口”显示 OK。但是当我关闭一个窗口时,该窗口关闭正常,但我无法关闭其他窗口!我的意思是,如果我有 3 个窗口,第一个窗口关闭正常(任何创建顺序),其他 2 个窗口在按下“X”时没有响应
  • 我认为是因为Thread.currentThread().interrupt() 中断了Java-main-thread。
  • 我该怎么办?我的意思是,我应该如何更改代码,哪一部分?
  • 如果你注释掉这一行会发生什么?
【解决方案2】:

如果您只是希望您的应用程序在 JFrame 关闭时退出,那么您就大错特错了。摆脱所有 Thread 对象和 Runnables。 Swing 应用程序在事件分派线程 (EDT) 中运行。只有在需要执行磁盘或网络 I/O 等操作时,才应使用后台线程。

在 EDT 中创建/显示 JFrame。如果将JFrame的默认关闭操作设置为DISPOSE_ON_CLOSE,那么当所有窗口都关闭后,主线程将正常终止。

public class MyApp {

    public static void main( String[] args ) {
        EventQueue.invokeLater( new Runnable() {
            public void run() {
                MyWindow w = new MyWindow();
                w.setVisible( true );
            }
        } );
    }

    private static class MyWindow extends JFrame {

        // Simplified reference counting
        private static AtomicInteger frameCount = new AtomicInteger( 0 );
        public MyWindow() {
            super("Frame " + frameCount.incrementAndGet() );   
            this.setSize( 400, 300 );
            this.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
            JButton button = new JButton("New Window");
            button.addActionListener( new ActionListener() {

                @Override
                public void actionPerformed( ActionEvent e ) {
                    MyWindow w = new MyWindow();
                    w.setVisible( true );
                }
            } );

            this.getContentPane().add( button );
            // ignore reference count button for now
        }

    }
}

【讨论】:

  • 这不会按预期工作,因为如果您关闭一个框架,它就会退出并且不会等到最后一个框架关闭。但当然,所有线程和可运行文件都不是必需的。
  • @Recode 你是对的。我将其更改为 DISPOSE_ON_CLOSE 并且可以正常工作。还要注意使用ActionListener,它比MouseListener 更适合单击按钮。
  • 是的,没错,使用ActionListener 是按钮点击的常用方式。但我不确定这个程序是否在最后一个窗口关闭时退出。
  • 我测试了它,它为我退出了。通常,一旦所有可显示的 Swing/AWT 组件都消失(并且没有其他线程),VM 将退出,但不能保证。不同的 JVM 可能表现不同。
猜你喜欢
  • 1970-01-01
  • 2010-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-25
  • 1970-01-01
  • 2017-05-06
相关资源
最近更新 更多