You've created a Java application that adds a new row to a JTable each second for 10 consecutive seconds. It consists of three classes:
The main class that gets called once the program is started
public class JarBundlerProblem { public static void main(String[] args) { System.err.println("Initializing controller"); new Controller(); } }
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(); } } } }
And finally, the 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}); } }
Since you're developing for OS X, and you need to be able to associate your application with a certain file type (let's say .jarbundlerproblem), you have to bundle your JAR file into an APP using Apple Jar Bundler. You have done this successfully, your application opens, counts to ten, writing out each second.
By default, double-clicking a .jarbundlerproblem, and associating the file with your application, will not pass the file I double-clicked as an argument to the application. Apparently, this is just Java on OS X works.
Since you need to be able to see what file was double-clicked, you're using OSXAdapter which is a Java library made by Apple for the purpose. This, you've implemented by altering the constructor of your 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(); } }
But after this (minor) modification, your application starts acting up. Sometimes, it doesn't open, even though you 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.
It looks like you're blocking the event dispatch thread (EDT). SwingWorker would be a better choice, but this example implements Runnable.
As an aside, this example shows one approach to auto-scrolling a JTable. Click on the thumb to suspend scrolling; release to resume.
Addendum: Your application lags for 10 seconds on startup. As this is the exact time for which the Controller sleeps, it's surely sleeping on the EDT. An sscce would be dispositive. Instead, do the work on another thread and update the model on the EDT. SwingWorker has a process() method that does so automatically, or you can use invokeLater() as shown below. Until your application is correctly synchronized, there's little hope of getting Apple events to work.
Addendum: You can invoke isDispatchThread() in the Controller to check. The project cited includes a .dmg with a Mac application and an ant file that builds the bundle in situ via target dist2.
Addendum: See also the alternate approaches shown here.
The above is the detailed content of Why does my Java application lag or terminate when using OSXAdapter to handle .jarbundlerproblem file associations?. For more information, please follow other related articles on the PHP Chinese website!