Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
607 views
in Technique[技术] by (71.8m points)

multithreading - Update JTextField from another thread in Java

I'm making a game client/server and I'm having a new thread update some info on the client GUI (which is using Swing). I'm trying to use SwingUtilities but it's not working. Also, I heard SwingUtilities creates a new thread everytime you use it so I'm looking for a new way as well (I have 10 or so JTextFields to be updated). Is there a way to do it without using SwingUtilities? Here is what I have right now.

SwingUtilities.invokeLater(    
        new Runnable() {    
           public void run()    
           {    
              Client.status.setText("status = "+status); 
           }    
        });
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Interestingly, just recently I encountered a similar issue, so In order to get over this I used SwingUtilities.invokeAndWait(Runnable runnable), that's what made the SSCCE I was creating to work as expected, though if I change all calls to invokeAndWait() with invokeLater(), one can clearly see the difference between the two things.

A quote from Java Doc says :

Causes doRun.run() to be executed synchronously on the AWT event dispatching thread. 
This call blocks until all pending AWT events have been processed and 
(then) doRun.run() returns. This method should be used when an application thread 
needs to update the GUI.

This is a small program I had made as an SSCCE to represent a Bubble Sort Animation :

import javax.swing.*;

public class BubbleSortFrame extends JFrame
{
    private BubbleSortView contentPane;

    private void displayGUI()
    {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        contentPane = new BubbleSortView();
        setContentPane(contentPane);
        pack();
        setLocationByPlatform(true);
        setVisible(true);
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                new BubbleSortFrame().displayGUI();
            }
        });
    }
}

import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.InvocationTargetException;
import javax.swing.*;

public class BubbleSortView extends JPanel
{
    private JLabel sizeLabel;
    private JTextField sizeField;
    private JTextField[] vField;
    private JLabel[] vLabel;
    private JButton startButton, createButton;
    private int size;
    private JPanel createPanel, animationPanel;

    private BubbleSort bubbleSort;

    public BubbleSortView()
    {
        size = 5;
        displayAndCreateGUI();
    }

    private void displayAndCreateGUI()
    {
        setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        setOpaque(true);
        setBackground(Color.WHITE);
        JPanel basePanel = new JPanel();
        basePanel.setLayout(new GridLayout(2, 1, 5, 5));
        basePanel.setOpaque(true);
        basePanel.setBackground(Color.WHITE);

        JPanel topPanel = new JPanel();
        topPanel.setOpaque(true);
        topPanel.setBackground(Color.WHITE);
        topPanel.setBorder(
            BorderFactory.createTitledBorder("Input : "));
        topPanel.setLayout(new GridLayout(2, 1, 5, 5)); 
        /*
         * This will act as the area
         * for taking the input for
         * number of elements in an Array.
         */
        JPanel sizePanel = new JPanel();
        sizePanel.setOpaque(true);
        sizePanel.setBackground(Color.WHITE);
        sizeLabel = new JLabel("Enter Number of Elements : ");
        sizeField = new JTextField(10);
        createButton = new JButton("CREATE");

        /*
         * This will act as the area
         * where we will specify the values
         * for each index in an Array.
         */
        createPanel = new JPanel();
        createPanel.setOpaque(true);
        createPanel.setBackground(Color.WHITE);
        createPanel.setBorder(
            BorderFactory.createTitledBorder("Please Enter values for an Array : "));
        createPanel.setVisible(false);      

        animationPanel = new JPanel();
        animationPanel.setOpaque(true);
        animationPanel.setBackground(Color.WHITE);
        animationPanel.setBorder(
            BorderFactory.createTitledBorder("Animation : "));
        animationPanel.setVisible(false);   

        createButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent ae)
            {
                if (sizeField.getDocument().getLength() > 0)
                {
                    size = Integer.parseInt(sizeField.getText());
                    vField = new JTextField[size];
                    createPanel.setVisible(true);
                    for (int i = 0; i < size; i++)
                    {
                        vField[i] = new JTextField(5);
                        /*
                         * Adding the Listener to the
                         * last JTextField on the Right 
                         * Side.
                         */
                        if (i == (size - 1)) 
                        {
                            vField[i].addActionListener(new ActionListener()
                            {
                                @Override
                                public void actionPerformed(ActionEvent ae)
                                {
                                    animationPanel.setLayout(
                                            new GridLayout(1, size, 2, 2));
                                    animationPanel.setVisible(true);
                                    vLabel = new JLabel[size];
                                    for (int i = 0; i < size; i++)
                                    {
                                        vLabel[i] = new JLabel(
                                            vField[i].getText(), JLabel.CENTER);
                                        vLabel[i].setOpaque(true);
                                        vLabel[i].setBackground(Color.YELLOW);
                                        vLabel[i].setForeground(Color.RED);
                                        animationPanel.add(vLabel[i]);
                                    }
                                    animationPanel.revalidate();
                                    animationPanel.repaint();
                                    bubbleSort = new BubbleSort(vLabel, size);
                                    Thread t = new Thread(bubbleSort);
                                    t.start();
                                }
                            });
                        }
                        createPanel.add(vField[i]);
                    }
                    createPanel.revalidate();
                    createPanel.repaint();
                    createButton.setEnabled(false);
                }
                else
                    size = 5;
            }
        });
        sizePanel.add(sizeLabel);
        sizePanel.add(sizeField);
        sizePanel.add(createButton);

        /*
         * Initializing JTextField Array
         * so that it can be first presented
         * to the USER to take input for
         * 5 values.
         */
        //for (int i = 0; i < size; i++)
        //  vField[i] = new JTextField(5);
        topPanel.add(sizePanel);
        topPanel.add(createPanel);
        basePanel.add(topPanel);
        basePanel.add(animationPanel);
        add(basePanel);
    }

    private class BubbleSort implements Runnable
    {
        private int[] arr;
        private JLabel[] vLabel;
        private int size;
        private int pass;

        public BubbleSort(JLabel[] label, int size)
        {
            vLabel = label;
            this.size = size;
            pass = 1;
            for (int i = 0; i < size; i++)
                System.out.print("" + vLabel[i].getText() + "");
            System.out.println("");
        }

        @Override
        public void run()
        {
            try
            {
                bubbleSorting();
            }
            catch (InvocationTargetException ite)
            {
                ite.printStackTrace();
            }
            catch(InterruptedException ie)
            {
                ie.printStackTrace();
            }
        }

        private void bubbleSorting() 
            throws InterruptedException, InvocationTargetException
        {
            while (pass < size)
            {
                for (int i = 0; i < (size - pass); i++)
                {
                    final int j = i;
                    SwingUtilities.invokeAndWait(new Runnable()
                    {
                        @Override
                        public void run()
                        {
                            vLabel[j].setBackground(Color.RED);
                            vLabel[j].setForeground(Color.WHITE);
                            vLabel[j + 1].setBackground(Color.RED);
                            vLabel[j + 1].setForeground(Color.WHITE);
                        }
                    });
                    try
                    {
                        Thread.sleep(1500);
                    }
                    catch(InterruptedException ie)
                    {
                        ie.printStackTrace();
                    }
                    int left = Integer.parseInt(vLabel[i].getText());
                    int right = Integer.parseInt(vLabel[i + 1].getText());
                    if (left > right)
                    {
                        String temp = vLabel[i].getText();
                        vLabel[i].setText(vLabel[i + 1].getText());
                        vLabel[i + 1].setText(temp);
                    }
                    SwingUtilities.invokeAndWait(new Runnable()
                    {
                        @Override
                        public void run()
                        {
                            vLabel[j].setBackground(Color.YELLOW);
                            vLabel[j].setForeground(Color.RED);
                            vLabel[j + 1].setBackground(Color.YELLOW);
                            vLabel[j + 1].setForeground(Color.RED);
                        }
                    });
                }
                System.out.println("Pass : " + pass + "Size : " + size);  
                SwingUtilities.invokeAndWait(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        vLabel[size - pass].setBackground(Color.GREEN);
                        vLabel[size - pass].setForeground(Color.BLUE);
                    }
                });
                pass++;
            }
            SwingUtilities.invokeAndWait(new Runnable()
            {
                @Override
                public void run()
                {
                    vLabel[0].setBackground(Color.GREEN);
                    vLabel[0].setForeground(Color.BLUE);
                }
            });
        }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...