Dynamically updating Jlist

I've been reading a lot on Swing but I've hit a dead end and I know you can help me. I've read lots of questions like Updating an JList but still I'm clueless as how to proceed. My problem is the same as the guy who asked the question I mentioned. I'm making a server and users will access it. This are my classes.

Server

private string name;
private string dateOfAccess;

@Override
public String toString() {
    // TODO Auto-generated method stub
    return nombreAmigo;
}

Main

 private DefaultListModel listModel = new DefaultListModel();
 private JList list=new JList(listModel);

and my ClientHandler

 public static List<Conexion> clientes=new ArrayList<Conexion>();

So, I'm going to be filling the clientes list from different threads as they connect to my server and I need to show them in my Jlist. Any suggestions on how to update it? I'm really stuck here Thanks!

Answers


Personally, I would have some kind of "client manager" that is responsible for collating all the clients into a centralised repository. This would be a singleton within your server. It could be queried at any time for a list of currently active users (and other management functions), but there should only ever be one active.

The manager would then fire notification events to interested parties (using an observe pattern).

One of these parties would be your UI. When a "connect" or "disconnect" event is raised, you will need to ensure that this is synced back the Event Dispatching Thread BEFORE you try and update the list model, for example...

public void userConnected(UserManagerEvent evt) { // You would need to define all this yourself...
    final Conexion user = evt.getConnection(); // You would need to define this event yourself...
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            listModel.addElement(user);
        }
    });
}

The actually implementation will come down to what it is you want to achieve and the way you want to achieve it, but this is the basic concept...

Updated with conceptual example

This is a basic, conceptual, example. An event is raised by the button, which simulates (for example) a connection. This event is then sent to the list, via an listener interface, where the model is updated

Events are generated from some other source and the UI is updated when they occur, classic observer pattern

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.w3c.dom.ls.LSInput;

public class UpdateListOnEvent {

    public static void main(String[] args) {
        new UpdateListOnEvent();
    }

    public UpdateListOnEvent() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class ConnectionEvent {

        private Date date;

        public ConnectionEvent(Date date) {
            this.date = date;
        }

        public Date getDate() {
            return date;
        }

    }

    public interface ConnectionListener {
        public void connectionEstablished(ConnectionEvent evt);
    }

    public class TestPane extends JPanel implements ConnectionListener {

        private JList list;
        private DefaultListModel<String> model;

        public TestPane() {
            setLayout(new BorderLayout());
            model = new DefaultListModel<>();
            list = new JList(model);
            add(new JScrollPane(list));
            EventPane eventPane = new EventPane();
            eventPane.addConnectionListener(this);
            add(eventPane, BorderLayout.SOUTH);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.dispose();
        }

        @Override
        public void connectionEstablished(ConnectionEvent evt) {
            model.addElement(DateFormat.getDateTimeInstance().format(evt.getDate()));
        }
    }

    public class EventPane extends JPanel {

        private List<ConnectionListener> listeners;
        private JButton update;

        public EventPane() {
            listeners = new ArrayList<>(5);
            setLayout(new GridBagLayout());
            update = new JButton("Update");
            update.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
//                    connectionEstablished(new Date());
                    fireConnectionEstablished(new Date());
                }
            });
            add(update);
        }

        public void addConnectionListener(ConnectionListener listener) {
            listeners.add(listener);
        }

        public void removeConnectionListener(ConnectionListener listener) {
            listeners.remove(listener);
        }

        protected ConnectionListener[] getConnectionListeners() {
            return listeners.toArray(new ConnectionListener[listeners.size()]);
        }

        protected void fireConnectionEstablished(Date date) {
            ConnectionListener[] listeners = getConnectionListeners();
            if (listeners != null && listeners.length > 0) {
                ConnectionEvent evt = new ConnectionEvent(date);
                for (ConnectionListener listener : listeners) {
                    listener.connectionEstablished(evt);
                }
            }
        }

    }
}

Need Your Help

Best practice using BIND or ON functions in jQuery

javascript jquery events jquery-mobile binding

Recently the jQuery team start recommending to use on instead of bind for binding events to the DOM.

WPF Fade Out on a control

c# wpf animation storyboard

In my WPF app, I have a feedback control that I want to appear after a user action completes (save data, delete...). The visibility is set to Hidden to begin and style set to the animateFadeOut st...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.