JAR Bundler使用OSXAdapter导致应用程序滞后或终止 [英] JAR Bundler using OSXAdapter causing application to lag or terminate

查看:144
本文介绍了JAR Bundler使用OSXAdapter导致应用程序滞后或终止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个简单的Java应用程序,每秒连续10秒为 JTable 添加一个新行。它由三个类组成。

I've created a simple Java application that each second for for 10 seconds consecutive seconds adds a new row to a JTable. It consists of three classes.

程序启动后调用的主类

public class JarBundlerProblem {
    public static void main(String[] args)
    {
        System.err.println("Initializing controller");
        new Controller();
    }
}

创建GUI并改变的控制器它通过 doWork()

A controller that creates the GUI and alters it through doWork()

public class Controller {
    public Controller()
    {
        doWork(null);
    }
    public static void doWork(String s)
    {
        GUI gui = new GUI();

        for (int i=0; i<10; i++)
        {
            gui.addRow("Line "+(i+1));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

最后,GUI

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

public class GUI {
    private JFrame frame = new JFrame();
    private DefaultTableModel model = new DefaultTableModel();
    private JTable table = new JTable(model);
    private JScrollPane pane = new JScrollPane(table);

    public GUI()
    {
        model.addColumn("Name");

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(pane);
        frame.pack();
        frame.setVisible(true);
    }
    public void addRow(String name)
    {
        model.addRow(new Object[]{name});
    }
}

因为我正在开发OS X,而我需要能够将我的应用程序与某种文件类型相关联(假设 .jarbundlerproblem ),我必须捆绑我的 JAR 使用 APP Introduction.htmlrel =nofollow> Apple Jar Bundler 。我已成功完成此操作,我的应用程序打开,计数到十,每秒写出。

Since I'm developing for OS X, and I need to be able to associate my application with a certain file type (let's say .jarbundlerproblem), I have to bundle my JAR file into an APP using Apple Jar Bundler. I have done this successfully, my application opens, counts to ten, writing out each second.

默认情况下,双击 .jarbundlerproblem ,并将文件与我的应用程序相关联,不会将我双击的文件作为参数传递给应用程序。显然,这只是OS X上的Java工作。

By default, double-clicking a .jarbundlerproblem, and associating the file with my application, will not pass the file I double-clicked as an argument to the application. Apparently, this is just Java on OS X works.

由于我需要能够看到双击的文件,我正在使用 OSXAdapter ,这是Apple为此目的制作的Java库。这个,我通过改变我的 Controller 类的构造函数来实现,并添加了另一个方法 registerForMacOSXEvents()

Since I need to be able to see what file was double-clicked, I'm using OSXAdapter which is a Java library made by Apple for the purpose. This, I've implemented by altering the constructor of my Controller class and added another method registerForMacOSXEvents():

public Controller()
{
    registerForMacOSXEvents();
    //doWork(null);
}
public void registerForMacOSXEvents() {
    try {
        OSXAdapter.setFileHandler(this, getClass().getDeclaredMethod("doWork", new Class[] { String.class }));
    } catch (Exception e) {
        System.err.println("Error while loading the OSXAdapter:");
        e.printStackTrace();
    }
}

但是经过这次(次要)修改后,我的应用程序启动了表现出色。有时,它不会打开,即使我可以在控制台中看到它刚刚启动(初始化控制器已写入),但经过几次尝试后,它最终会启动,但是前10秒窗口将完全空白,之后将添加10行。

But after this (minor) modification, my application starts acting up. Sometimes, it doesn't open, even though I can see in the Console that it just started (Initializing controller is written), but after a few attempts, it will eventually start, but the windows will be completely blank for the first 10 seconds, and after that, the 10 rows will be added.

现在,我一直在努力解决这个问题,似乎没有很多关于OSXAdapter和Jar Bundler的文档。我究竟做错了什么?或者我不应该首先使用OSXAdapter或Jar Bundler?

Now, I've struggled with this quite a bit, and it seems like there isn't a lot of documentation regarding neither OSXAdapter nor Jar Bundler. What am I doing wrong? Or shouldn't I be using OSXAdapter or Jar Bundler in the first place?

推荐答案

这样做后,我还不完全确信SwingWorker是一个更简单(又名:更好)的解决方案 - 仍然需要额外的线程同步(在工作线程和传入文件/名称的外部线程之间)。无论如何(借此机会学习,并由错误:),下面是基本想法的概念证明示例:

After doing it, I'm not fully convinced a SwingWorker is a simpler (aka: better) solution - still requires additional thread synching (between the worker thread and the "outer" thread which passes in the file/names). Anyway (taking the opportunity to learn, and be it by errors :), below is a crude proof of concept example for the basic idea:


  • 将Controller实现为SwingWorker,将外部线程的输入汇集到EDT中

  • 使其通过方法doWork(..)接受输入(来自适配器,fi)发布的输入

  • 实现doInBackground以成功发布输入

打开问题


  • 同步访问本地列表(不是并发专家,但非常确定需要完成)

  • 可靠地检测外线程的结束(这里只是在输入队列为空时停止)

欢迎反馈:-)

public class GUI {
    private JFrame frame = new JFrame();
    private DefaultTableModel model = new DefaultTableModel();
    private JTable table = new JTable(model);
    private JScrollPane pane = new JScrollPane(table);

    public GUI() {
        model.addColumn("Name");

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(pane);
        frame.pack();
        frame.setVisible(true);
    }

    public void addRow(String name) {
        model.addRow(new Object[] { name });
    }

    /**
     * Controller is a SwingWorker.
     */
    public static class Controller extends SwingWorker<Void, String> {
        private GUI gui;

        private List<String> pending;

        public Controller() {
            gui = new GUI();
        }

        public void doWork(String newLine) {
            if (pending == null) {
                pending = new ArrayList<String>();
                pending.add(newLine);
                execute();
            } else {
                pending.add(newLine);
            }
        }

        @Override
        protected Void doInBackground() throws Exception {
            while (pending.size() > 0) {
                publish(pending.remove(0));
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }

        /**
         * @inherited <p>
         */
        @Override
        protected void process(List<String> chunks) {
            for (String object : chunks) {
                gui.addRow(object);
            }
        }

    }

    /** 
     * Simulating the adapter.
     * 
     *  Obviously, the real-thingy wouldn't have a reference 
     *  to the controller, but message the doWork refectively 
     */
    public static class Adapter implements Runnable {

        Controller controller;

        public Adapter(Controller controller) {
            this.controller = controller;
        }

        @Override
        public void run() {
            for (int i=0; i<10; i++)
            {
                controller.doWork("Line "+(i+1));
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }
    public static void main(String[] args)
    {
        System.err.println("Initializing controller");
        new Adapter(new Controller()).run();
    }

    @SuppressWarnings("unused")
    private static final Logger LOG = Logger.getLogger(GUI.class.getName());
}

这篇关于JAR Bundler使用OSXAdapter导致应用程序滞后或终止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆