【问题标题】:GUI from separate thread来自单独线程的 GUI
【发布时间】:2016-03-18 10:16:16
【问题描述】:

尝试创建两个可以在不同线程中运行代码的独立格式。下面的代码创建了两种形式,但如果我按下其中一个上的按钮,我不能对另一个做同样的事情。它根本不执行代码。如何制作两个可以互不阻塞运行的简单表单?

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);
            }
        });

    }
}

更新

通过创建单独的线程更改main(),但得到相同的结果

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();

    }

【问题讨论】:

  • 您将它们添加到执行队列,而不是单独的线程。检查此帖子stackoverflow.com/questions/22534356/… 您可能想将EventQueue.invokeLater() 更改为new Thread(),然后使用Thread.start() 启动它们
  • 更改为 Thread(),但得到了相同的结果。问题正文 UPD 中的更多详细信息。
  • Swing 是单线程的,你无法改变这一点,所有事件都被发布到事件队列并由事件调度线程处理,更多细节请参阅Concurrency in Swing 并查看@ 987654323@ 至少一种可能的解决方案

标签: java multithreading swing


【解决方案1】:

@Nadir 或多或少是对的。

您将在 EventQueue 表示的同一线程中启动两个窗口。

我认为 Swing 程序员更喜欢使用 SwingUtilities 来打开新的框架应用程序,但您可以通过更改方法 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();

这样你就会有两个不同的线程。在您的原始版本中,您只有一个线程。

更新:也改变你的主要方法

     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);
        }
    });

}

【讨论】:

  • 正如你所指出的,Swing 是单线程的,但它也不是线程安全的,所以如果你想从事件调度线程的上下文之外更新 UI 的状态,请小心;)
  • 我已经知道了。几年前我就学会了。也许阅读您的一些旧答案:-)
猜你喜欢
  • 2017-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多