user46759
user46759

Reputation: 103

How execute a class with main method with a Jbutton

I want to call and execute a class with main method from another class which has main method too by clicking on a Jbutton. The class of Example1 wich has main method run perfectly stand alone:

import org.nlogo.app.App;
public class Example1 {
  public static void main(String[] argv) {
    App.main(argv);
    try {
      java.awt.EventQueue.invokeAndWait(
    new Runnable() {
      public void run() {
        try {
          App.app().open("C:/Users/fmar825/Desktop/fire.nlogo");
        }
        catch(java.io.IOException ex) {
          ex.printStackTrace();
        }}});
    }
    catch(Exception ex) {
      ex.printStackTrace();
    }
  }
}

But when I call it from another class to be execute with clicking on Jbutton.

  private void okbtnActionPerformed(java.awt.event.ActionEvent evt) {                                      
    
        Example1 object=new Example1();
        try {
               object.main(new String[0] );
            } catch (Exception e) {
                e.printStackTrace();
            }
    
    } 

I got following Error message.

ava.lang.Error: Cannot call invokeAndWait from the event dispatcher thread
	at java.awt.EventQueue.invokeAndWait(EventQueue.java:1289)
	at java.awt.EventQueue.invokeAndWait(EventQueue.java:1282)
	at org.nlogo.awt.EventQueue$.invokeAndWait(EventQueue.scala:19)
	at org.nlogo.app.App$.main(App.scala:150)
	at org.nlogo.app.App.main(App.scala)
	at Example1.main(Example1.java:4)
	at User.okbtnActionPerformed(User.java:995)
	at User.access$1600(User.java:31)
	at User$19.actionPerformed(User.java:604)
	at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
	at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2346)
	at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
	at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
	at java.awt.Component.processMouseEvent(Component.java:6525)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
	at java.awt.Component.processEvent(Component.java:6290)
	at java.awt.Container.processEvent(Container.java:2234)
	at java.awt.Component.dispatchEventImpl(Component.java:4881)
	at java.awt.Container.dispatchEventImpl(Container.java:2292)
	at java.awt.Component.dispatchEvent(Component.java:4703)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4898)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4533)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4462)
	at java.awt.Container.dispatchEventImpl(Container.java:2278)
	at java.awt.Window.dispatchEventImpl(Window.java:2739)
	at java.awt.Component.dispatchEvent(Component.java:4703)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:746)
	at java.awt.EventQueue.access$400(EventQueue.java:97)
	at java.awt.EventQueue$3.run(EventQueue.java:697)
	at java.awt.EventQueue$3.run(EventQueue.java:691)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:86)
	at java.awt.EventQueue$4.run(EventQueue.java:719)
	at java.awt.EventQueue$4.run(EventQueue.java:717)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:716)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
java.lang.NullPointerException
	at org.nlogo.window.RuntimeErrorDialog.suppressJavaExceptionDialogs(RuntimeErrorDialog.java:63)
	at org.nlogo.app.App.handle(App.scala:779)
	at org.nlogo.util.Exceptions$.handle(Exceptions.scala:21)
	at org.nlogo.app.App$$anon$7.uncaughtException(App.scala:305)
	at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1057)
	at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
	at java.awt.EventDispatchThread.processException(EventDispatchThread.java:223)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:215)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Upvotes: 0

Views: 1592

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347204

Change invokeAndWait to invokeLater

Essentially what's happening is, your JButton is executing the ActionListener from within the context of the Event Dispatching Thread, this is just how it works. When you call Example1.main, it attempts to invoke the Runnable within the context of the Event Dispatching Thread, but block the current thread (which is the EDT) until it completes. This is, obviously unachievable and in order to prevent a possible thread dead lock, invokeAndWait will throw an exception.

You "could" also change the code in Example1 to something like...

Runnable runnable = new Runnable() {
    public void run() {
        try {
            App.app().open("C:/Users/fmar825/Desktop/fire.nlogo");
        } catch(java.io.IOException ex) {
            ex.printStackTrace();
        }
    }
};

if (EventQueue.isDispatchThread()) {
    runnable.run();
} else {
    try {
        java.awt.EventQueue.invokeAndWait(runnable);
    } catch(Exception ex) {
        ex.printStackTrace();
    }    
}

Which checks to see if the current thread is the EDT and if so, simply calls the run method of the Runnable directly, otherwise it calls invokeAndWait. This will better mimic the original behavior when called from within the context of the EDT

Runnable example

It works just fine for me...

Parent (GUI) class...

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Parent {

    public static void main(String[] args) {
        new Parent();
    }

    public Parent() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());
            JButton makeItSo = new JButton("Make it so");
            makeItSo.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Child.main(new String[0]);
                }
            });
            add(makeItSo);
        }

    }

}

Child (other main) class

import java.awt.EventQueue;
import javax.swing.JOptionPane;

public class Child {

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            public void run() {
                JOptionPane.showMessageDialog(null, "I'm a banana");
            }
        };

        if (EventQueue.isDispatchThread()) {
            System.out.println("Execute within the EDT");
            runnable.run();
        } else {
            try {
                System.out.println("Invoke and Wait");
                java.awt.EventQueue.invokeAndWait(runnable);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }

    }
}

Upvotes: 1

Related Questions