1

Trying to create two independent forma that could run code in separate threads. Code below creates two forms , but if I press button on one of them I can't do the same with another. It simply not executes code. How to make two simple forms that could run non blocking each other?

public class MnemonicEx1 extends JFrame
{

    public JeasiHandler jh = null;
    private Log log = Log.getLog();

    public MnemonicEx1()
    {

        initUI();
    }

    private void initUI()
    {

        JButton btnAuth = new JButton("1");

        btnAuth.addActionListener(new ActionListener()
        {

            // @Override
            public void actionPerformed(ActionEvent e)
            {

                System.out.println("starting");
                for (int i = 0; i < 1000; i++)
                {
                    try
                    {
                        Thread.sleep(100);
                        System.out.println(Integer.toString(i));
                    } catch (InterruptedException ex)
                    {
                        ex.printStackTrace();
                    }
                }

                System.out.println("finishing");

            }


        });

        btnAuth.setMnemonic(KeyEvent.VK_B);

        //createLayout(btnAuth);
        createLayout(btnAuth);

        setTitle("****");
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    private void createLayout(JComponent authButn)
    {

        Container pane = getContentPane();
        GroupLayout gl = new GroupLayout(pane);
        pane.setLayout(gl);

        gl.setAutoCreateContainerGaps(true);

        int i = 0;
        gl.setHorizontalGroup(
                gl.createSequentialGroup()
                .addComponent(authButn)
        );

        gl.setVerticalGroup(gl.createParallelGroup()
                .addComponent(authButn)
        );

        pack();
    }

    public static void main(String[] args)
    {

        EventQueue.invokeLater(new Runnable()
        {

            public void run()
            {
                MnemonicEx1 ex = new MnemonicEx1();
                ex.setVisible(true);
            }
        });

        EventQueue.invokeLater(new Runnable()
        {

            public void run()
            {
                MnemonicEx1 ex = new MnemonicEx1();
                ex.setVisible(true);
            }
        });

    }
}

UPD

Changed main() by creating separate threads , but got the same result

public static void main(String[] args)
    {

        new Thread (new Runnable()
        {

            public void run()
            {
                MnemonicEx1 ex = new MnemonicEx1();
                ex.setVisible(true);
            }
        }).start();

        new Thread(new Runnable()
        {

            public void run()
            {
                MnemonicEx1 ex = new MnemonicEx1();
                ex.setVisible(true);
            }
        }).start();

    }
vico
  • 17,051
  • 45
  • 159
  • 315
  • You are adding them to the execution queue, not to separate threads. Check this post http://stackoverflow.com/questions/22534356/java-awt-eventqueue-invokelater-explained You might want to change the `EventQueue.invokeLater()` for `new Thread()` and then start them using `Thread.start()` – Nadir Mar 18 '16 at 10:24
  • Changed to Thread(), but got the same result. More details in question body UPD. – vico Mar 18 '16 at 10:34
  • 1
    Swing is single threaded, nothing you can do to change that, all events are posted to the event queue and processed by the Event Dispatching Thread, see [Concurrency in Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) for more details and have a look at [Worker Threads and SwingWorker](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html) for at least one possible solution – MadProgrammer Mar 18 '16 at 10:56

1 Answers1

3

@Nadir is more or less right.

You are launching both windows in the same thread represented by EventQueue.

I think swing programmers prefer to use SwingUtilities for opening new frame applications but you can achieve your goal changing your method actionPerformed

        // @Override
        public void actionPerformed(ActionEvent e) {

            new Thread() {
                @Override
                public void run() {
                    System.out.println("starting");
                    for (int i = 0; i < 1000; i++)
                    {
                        try
                        {
                            Thread.sleep(100);
                            System.out.println(Integer.toString(i));
                        } catch (InterruptedException ex) {
                            ex.printStackTrace();
                        }
                    }
                     System.out.println("finishing");
                }
            }.start();

That way you'll have two different threads. In your original version you only had one thread.

UPDATED: Change also your main method

     public static void main(String[] args)
     {

        SwingUtilities.invokeLater(new Runnable() {

        public void run() {
            MnemonicEx1 ex = new MnemonicEx1();
            ex.setVisible(true);
        }
        });

        SwingUtilities.invokeLater(new Runnable() {

        public void run()
        {
            MnemonicEx1 ex = new MnemonicEx1();
            ex.setVisible(true);
        }
    });

}
RubioRic
  • 2,442
  • 4
  • 28
  • 35
  • As you have noted, Swing is single threaded, but it's also not thread safe, so beware if you want to update the state of the UI from outside of the Event Dispatching Thread's context ;) – MadProgrammer Mar 18 '16 at 10:57
  • I already knew that. I learnt it some years back. Maybe reading some of your old answers :-) – RubioRic Mar 18 '16 at 11:06