0

I want to update jpanel in clients GUIs from the value I get from server continuously. But I can't see anything on the window.I can see the client frame if I set only one time but I need something like

while( get data from server != null){
   //update the jpanel
   // I tried
  frame.panel.setValue(data from server)
  frame.repaint()
  //and this one too
  frame.remove(old panel)
  frame.add(new JCustomPanel(with new value))
  frame.repaint()
}

I can't share my code because my teacher prohibited it but I can't solve either.Please help me :c

  • This obviously blocks the GUI thread. You can't do that. Use a background worker to read the data and send it to the GUI: https://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html – markspace Feb 06 '22 at 18:12
  • Don't add/remove components. Instead update the data (model) of the existing components. – camickr Feb 07 '22 at 04:15
  • See an example [here](https://stackoverflow.com/questions/58526874/updating-jlabel-text-from-another-thread-in-real-time/58528000#58528000) – c0der Feb 08 '22 at 06:44

1 Answers1

0

You need to do two things. First of all you need to create another thread, that will work with data independently from the main thread. Secondly, you need to use SwingUtilities.invokeLater method. This is a full example, that shows how it works. It changes label every second (Thread.sleep is used for delay in this example, don't use it in your real code).

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
  

public class NewMain {
  
    // JFrame
    static JFrame frame;
  
    // JLabel
    static JLabel label;
  
    // Main class
    public static void main(String[] args)  {
        frame = new JFrame("panel");
        label = new JLabel();
        // Creating a panel to add label
        JPanel panel = new JPanel();
        panel.add(label);
        // Adding panel to frame
        frame.add(panel);
        // Setting the size of frame
        frame.setSize(300, 300);
        frame.show();
        doLoop();
    }
    
    private static void doLoop() {
        Thread newThread = new Thread(() -> {
            while (true) {
                SwingUtilities.invokeLater(() -> {
                    label.setText(new java.util.Date().toString());
                });
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                    Logger.getLogger(NewMain.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
        newThread.start();
    }
}
Pavel_K
  • 10,748
  • 13
  • 73
  • 186
  • `Thread.sleep()` is only good for faking data in an example like this. In real code, do NOT call Thread.sleep(), wait for data to be available, then call `invokeLater()`. (P.S. I still like a `SwingWorker` better.) – markspace Feb 06 '22 at 18:13
  • @markspace I used `Thread.sleep()` only for this my example. – Pavel_K Feb 06 '22 at 18:14
  • I figured you knew that, but I'm just letting the OP and any other readers know that it's really bad in "real" code to do that. – markspace Feb 06 '22 at 18:15
  • thank you so much. It's working now but updated client GUI draws faster than server side. in invokeLater I called a function to update panel as `getContentPane().remove(old panel); add(new Panel(newlist)); getContentPane().doLayout(); getContentPane().invalidate(); getContentPane().validate(); ` where I am doing wrong : –  Feb 06 '22 at 21:39
  • @BB On StackOverflow it is required to ask a separate question for every different problem. Your origin question was about updating swing element in loop. I showed you how to do it. If my answer helped you, you should accept it. If you have another problem, then you should ask another question and in it you must show the code you use to work with your server, because without it it is impossible to answer your question. By the way, try not to add/remove panel for displaying info. Use elements like label, etc and only update their text values. – Pavel_K Feb 07 '22 at 07:01
  • _client GUI draws faster than server side_ use a Model class and listen to changes in the data. Update GUI only when data is changed. See an example [here](https://stackoverflow.com/a/58528000/3992939) – c0der Feb 08 '22 at 06:49