在Java中从另一个线程更新JTextField

在Java中从另一个线程更新JTextField,java,multithreading,swing,user-interface,client,Java,Multithreading,Swing,User Interface,Client,我正在制作一个游戏客户端/服务器,我正在让一个新线程更新客户端GUI(使用Swing)上的一些信息。我试着使用Swinguities,但它不起作用。另外,我听说SwingUtilities每次使用都会创建一个新线程,所以我也在寻找一种新方法(我有10个左右的JTextFields需要更新)。有没有一种方法可以不用勇气去做呢?这是我现在拥有的 SwingUtilities.invokeLater( new Runnable() { public

我正在制作一个游戏客户端/服务器,我正在让一个新线程更新客户端GUI(使用Swing)上的一些信息。我试着使用Swinguities,但它不起作用。另外,我听说SwingUtilities每次使用都会创建一个新线程,所以我也在寻找一种新方法(我有10个左右的JTextFields需要更新)。有没有一种方法可以不用勇气去做呢?这是我现在拥有的

SwingUtilities.invokeLater(    
        new Runnable() {    
           public void run()    
           {    
              Client.status.setText("status = "+status); 
           }    
        });

我不知道你是从哪里听说“SwingUtilities创建新线程”的,但我认为你要么误解了,要么被错误地告知了
SwingUtilities.invokeLater
Runnable
放在事件调度器队列的末尾。然后,队列在自己的线程上下文中(及时)处理此事件,调用
Run
,没有为此进程创建“新”线程

至于你的问题

您可能需要在字段父容器上调用
validate()
(可能还需要调用
repaint()
),以鼓励其更新;)


不,没有任何其他方法可以跨线程同步UI,这就是为什么
SwingUtilities

有趣的是,最近我遇到了一个类似的问题,所以为了克服这个问题,我使用了,这就是我创建的,虽然如果我用将所有调用更改为,人们可以清楚地看到两者之间的区别

Java Doc的一句话说:

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.
这是我制作的一个小程序,用于表示气泡排序动画:

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.*;
导入java.awt.event.*;
导入java.lang.reflect.InvocationTargetException;
导入javax.swing.*;
公共类BubbleSortView扩展了JPanel
{
私人JLabel sizeLabel;
私有JTextField sizeField;
私有JTextField[]vField;
私人JLabel[]vLabel;
私有JButton开始按钮、createButton;
私有整数大小;
私有JPanel createPanel、animationPanel;
私人泡泡港泡泡港;
公共BubbleSortView()
{
尺寸=5;
displayAndCreateGUI();
}
私有void displayAndCreateGUI()
{
setBorder(BorderFactory.createEmptyByOrder(5,5,5,5));
set不透明(true);
挫折地面(颜色:白色);
JPanel basePanel=新的JPanel();
basePanel.setLayout(新的网格布局(2,1,5,5));
basePanel.set不透明(true);
底板.立根底板(颜色.白色);
JPanel-topPanel=新的JPanel();
topPanel.Set不透明(真);
托帕内尔。挫折地面(颜色。白色);
托帕内尔订单(
createTitleBorder(“输入:”);
topPanel.setLayout(新的GridLayout(2,1,5,5));
/*
*这将作为一个区域
*用于将输入用于
*数组中的元素数。
*/
JPanel sizePanel=新的JPanel();
sizePanel.set不透明(true);
sizePanel.setBackground(颜色:白色);
sizeLabel=newjlabel(“输入元素数:”);
sizeField=新的JTextField(10);
createButton=新的JButton(“创建”);
/*
*这将作为一个区域
*我们将在其中指定值
*对于数组中的每个索引。
*/
createPanel=newjpanel();
createPanel.set不透明(true);
createPanel.setBackground(颜色:白色);
createPanel.setOrder(
createTitleBorder(“请为数组输入值:”);
createPanel.setVisible(false);
animationPanel=新的JPanel();
animationPanel.set不透明(true);
animationPanel.setBackground(颜色:白色);
animationPanel.setOrder(
createTitleBorder(“动画:”);
animationPanel.setVisible(false);
createButton.addActionListener(新ActionListener()
{
@凌驾
已执行的公共无效行动(行动事件ae)
{
如果(sizeField.getDocument().getLength()>0)
{
size=Integer.parseInt(sizeField.getText());
vField=新的JTextField[大小];
createPanel.setVisible(true);
对于(int i=0;iimport 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() + "\t");
            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 + "\tSize : " + 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);
                }
            });
        }
    }
}