我正在编写一个用于图像分析的Java应用程序,该应用程序有时会打开ImageJ

ImageJ ij = new ImageJ();


并且还会打开一个包含ImagePlus的Windows。

现在,每当首先关闭ImageJ时,按下关闭按钮时ImagePlus都不会关闭。另一种方法可行,但是在两种情况下,关闭ImageJ后都会引发异常:

java.lang.reflect.InvocationTargetException
    at java.awt.EventQueue.invokeAndWait(EventQueue.java:1288)
    at java.awt.Window.doDispose(Window.java:1209)
    at java.awt.Window.dispose(Window.java:1147)
    at ij.ImageJ.run(ImageJ.java:784)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalArgumentException: null source
    at java.util.EventObject.<init>(EventObject.java:56)
    at java.awt.AWTEvent.<init>(AWTEvent.java:337)
    at java.awt.event.InvocationEvent.<init>(InvocationEvent.java:285)
    at java.awt.event.InvocationEvent.<init>(InvocationEvent.java:174)
    at sun.awt.X11.XBaseMenuWindow.dispose(XBaseMenuWindow.java:907)
    ...


我不知道这两种情况是否相关。

关于如何强制ImageJ关闭所有窗口的任何建议?

最佳答案

例外

在Linux上使用OpenJDK 7时会发生这种情况。 fixed in Java 8是例外。

另外:请注意,该异常并不是您看到的退出问题的真正原因。

处置问题

ImageJ 1.x的应用处置非常混乱。 (有关一些技术讨论,请参见this news post。)它实际上主要是要作为独立的应用程序运行,并且大多在exitWhenQuitting标志设置为true的情况下进行了测试,以便JVM在关闭主窗口时关闭。因此,以不同的方式使用ImageJ会导致挂起图像窗口也就不足为奇了。

我已经测试了各种解决方法,例如:

ij.addWindowListener(new WindowAdapter() {
    @Override
    public void windowClosing(final WindowEvent e) {
        // dispose all image windows
        for (final int id : WindowManager.getIDList()) {
            final ImagePlus imp = WindowManager.getImage(id);
            if (imp == null) continue;
            final ImageWindow win = imp.getWindow();
            if (win != null) win.dispose();
        }
        // dispose all other ImageJ windows
        for (final Window w : WindowManager.getAllNonImageWindows()) {
            w.dispose();
        }
    }
});


但是它们都不如人们所希望的那样工作。根据上面链接的新闻,我在ImageJ2中完成戒烟工作花了我数周的开发和实验时间。

这是一些使用ImageJ2的代码,几乎可以按照您想要的方式运行:

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

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.WindowConstants;

import net.imagej.ImageJ;

public class IJDispose {

  public static void main(final String... args) {
    final ImageJ ij = new ImageJ();
    ij.ui().showUI();

    final JFrame frame = new JFrame("Hello");
    final JButton b = new JButton("Close ImageJ");
    b.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(final ActionEvent e) {
        ij.getContext().dispose();
      }
    });
    frame.getContentPane().add(b);
    frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
  }

}


启动它后,按Shift + B打开Blobs示例图像。然后从非ImageJ框架中单击“关闭ImageJ”按钮。您会看到ImageJ主窗口和图像窗口按需要进行处置(使用this code from ImageJ Legacy)。

但是,(至少)存在三个问题:


此示例未将ij.getContext().dispose()调用与实际的ImageJ1 UI窗口关闭事件挂钩。这样做并不是一件容易的事(我是说,在最近的这段代码中没有做过深入的探讨)。
部署ImageJ以及额外的JFrame之后,应该关闭JVM。实际上,我们为此付出了很多努力。但这实际上不适用于当前版本的ImageJ,大概是由于某个地方有一些未处理的资源。这是一个错误。
在ImageJ主窗口上单击X会关闭整个JVM,因为ImageJ1的exitWhenQuitting标志得到set to true。您可以自己将其切换回伪造,但这实际上是棘手的,因为类加载问题与ImageJ2在运行时使用Javassist修补ImageJ1有关。


下一个问题是:您真的有多需要这个功能才能工作?

关于java - 如何强制ImageJ关闭所有窗口而没有关闭事件错误?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33543833/

10-10 14:40