Updating JTextField from another thread in Java

I am creating a game client / server, and I have a new update to the flow of information about the client GUI (which uses Swing). I am trying to use SwingUtilities, but it does not work. Also, I heard that SwingUtilities creates a new thread every time you use it, so I'm looking for a new way (I have 10 or so JTextFields to update). Is there a way to do this without using SwingUtilities? Here is what I have right now.

SwingUtilities.invokeLater( new Runnable() { public void run() { Client.status.setText("status = "+status); } }); 
+3
source share
2 answers

I don’t know where you heard that “SwingUtilities creates a new thread”, but I think you misunderstood or were misinformed. SwingUtilities.invokeLater puts Runnable at the end of the event dispatcher queue. Then the queue processes this event inside the thread’s own context (by time), calling Run ; no “new” thread is created for this process.

Regarding your question.

You may need to call validate() (and possibly repaint() ) in the parent field container so that it updates;)

And no, there is no other way to synchronize the user interface over threads, which is the reason for SwingUtilities

+4
source

Interestingly, I recently encountered a similar problem, so in order to overcome this, I used SwingUtilities.invokeAndWait (Runnable runnable) , which made SSCCE I created for work as expected, although if I change all the calls to invokeAndWait ( ) with invokeLater () , the difference between the two things is clearly visible.

A quote from the 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 that I did as SSCCE to represent 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() + "\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); } }); } } } 
+5
source

Source: https://habr.com/ru/post/1443639/


All Articles