1

As the title says, when i try to dynamically add an element to a JList, which is inside a JScrollPane, it becomes empty. I think it has something to do with multithreading.

The GUI is a simple monitoring interface for a server I am working on. I'll post parts of the code I think is responsable for this:

But first, this is the frame:

public class EventMonitor extends JFrame{

private JList eventList;
private DefaultListModel<String> dlm ;
JScrollPane jPane;

public EventMonitor()
{
    super("Server Monitor");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLayout(new FlowLayout());

    dlm = new DefaultListModel<String> ();

    eventList = new JList();
    jPane = new JScrollPane(eventList);
    jPane.setPreferredSize(new Dimension(950, 600));
    add(jPane);

}

public void addEvent(String event)
 {
    dlm.addElement(event);
    eventList.setModel(dlm);
    jPane.revalidate();
    jPane.repaint();

 }
}

In main() from Server class:

     //some code
    eventMonitor = new EventMonitor();
    eventMonitor.setBounds(250, 250, 1000, 650);
    eventMonitor.setVisible(true);
     //some other code
    eventMonitor.addEvent("Server is waiting for new connections..."); // this is shown in the list
    while(true)
        {
            ClientHandler clientHandler = new ClientHandler(listener.accept());// listener is ServerSocket
            clientList.add(clientHandler);
            clientHandler.start();
        }

This is what makes the list go empty: inClientHandler constructor:

public ClientHandler(Socket socket){
//some code
Server.addEvent("The client is: " + user.GetName() + ", with the ip:" + user.GetIPv4() + ", and using the port: "  + user.GetPORT());
//some more code 
} // where Server.addEvent(String event) just calls eventMonitor.addEvent(event)

After this, 'run' from 'ClientHandler' listens for messages and they are posted via Server.addEvent(), and it works without a problem, but when another client connects it goes empty again. The first event shown after the one in ClientHandler constructor makes the list whole (showing the event that made it empty too)

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
laurGanta
  • 175
  • 1
  • 1
  • 12
  • 2
    1- Swing is not thread safe and the call to `dlm.addElement(event);` should be done from within the context of the Event Dispatching Thread, wrapping in a `SwingUtilities.invokeLater` should help. 2- There should be no need for `eventList.setModel(dlm);`, `jPane.revalidate();`, `jPane.repaint();` within the `addEvent` method – MadProgrammer Dec 03 '14 at 07:15
  • For further reading I recommend: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/ – keuleJ Dec 03 '14 at 07:16
  • @keuleJ I'll read that. Thank you. – laurGanta Dec 03 '14 at 07:23

1 Answers1

2

It looks like you're blocking the UI thread in the loop - when you call accept(), that's going to wait for a new connection, which means the UI thread can't repaint the UI. You should do that in a separate thread.

All UI interactions should be performed in the UI thread though, e.g. using SwingUtilities.invokeLater.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194