Adding elements to JList in Swing Java
Asked Answered
O

4

10

I have a function that executes when a button is clicked. Suppose there is a loop to add 1 to 10 to a JList. I add that data to DefaultListModel. It works perfectly and the numbers get added. Then I added a Thread.sleep(1000) within the loop. But the output is different. I wanted to add 1 element every second. But now it waits for 10secs and the add all 1 to 10 together at the end of 10th second. Am I wrong anywhere?

List processList = listNumbers.getSelectedValuesList();
DefaultListModel resultList = new DefaultListModel();
listResult.setModel(resultList);

for (int i = 0; i < processList.size(); i++) {
    resultList.addElement(String.valueOf(i));
    try {
        Thread.sleep(1000);
    }
    catch (InterruptedException ex) {
    }
}
Oxus answered 16/9, 2011 at 8:56 Comment(0)
G
4

You should update your list in a separate thread otherwise you end up blocking the event dispatch thread.

Try the following:

final DefaultListModel model = new DefaultListModel();
final JList list = new JList(model);

//another thread to update the model
final Thread updater = new Thread() {
    /* (non-Javadoc)
     * @see java.lang.Thread#run()
     */
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            model.addElement(i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
};
updater.start();
Genna answered 16/9, 2011 at 9:18 Comment(8)
I still think that model.addElement(i) must be wrapped into invokeLater, please update your postSublimity
@Sublimity really? I am updating the model, which will in turn fire an event to a handler which will call repaint on the list. I believe this repaint call will queue a request for the event-dispatching thread to call paint, so it should be safe.Genna
true is that there are no updates on EDT, all are done past Thread.sleep(1000);, because all fireXxxXxx are out of EDTSublimity
I'll edit my post with examples for programaticaly block EDT with Thread.sleep(int) for correct and expected output to the GUISublimity
@Sublimity in my code, the model is updated out of the EDT, but the repaint calls which are performed by the model listeners are performed on the EDT. If you run my code, you will see that it produces the right output.Genna
in due all respect to your person, you are excelent Java coder, with clear and fast mind, but repaint (I know that alive EDT, in all cases) is for GUI hardiest methods as there exists, for your contributing here +1 by my person for answer (even was accepted) big -1Sublimity
-1 model updates must happen on the EDT (as @Sublimity already noted)Canonry
@Sublimity and kelopatra, very thanks to you both, it is a very finer level thing, which I was searching for.. Thanks much again..Jovitajovitah
S
7

don't use, really don't use Thread.sleep(int) during EventDispashThread, because sleep locked current Thread and in this case EventDispashThread, with un-expection output to the GUI, more in Concurency in Swing,

if you needed something to dealay, then add Items wrappend into Runneble#Thread, with output to the GUI wrapped into invokeLater, or the best way is using javax.swing.Timer

EDIT 1st. example how to programatically block EDT with Thread.sleep(int), because othewise doesn't works with expecting output to the GUI (code is very loonnnger as I want to code)

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ShakingButtonDemo implements Runnable {

    private JButton button;
    private JRadioButton radioWholeButton;
    private JRadioButton radioTextOnly;

    public static void main(String[] args) throws Exception {
        SwingUtilities.invokeLater(new ShakingButtonDemo());
    }

    @Override
    public void run() {
        radioWholeButton = new JRadioButton("The whole button");
        radioTextOnly = new JRadioButton("Button text only");
        radioWholeButton.setSelected(true);
        ButtonGroup bg = new ButtonGroup();
        bg.add(radioWholeButton);
        bg.add(radioTextOnly);
        button = new JButton("  Shake with this Button  ");
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                shakeButton(radioWholeButton.isSelected());
            }
        });
        JPanel p1 = new JPanel();
        p1.setBorder(BorderFactory.createTitledBorder("Shake Options"));
        p1.setLayout(new GridLayout(0, 1));
        p1.add(radioWholeButton);
        p1.add(radioTextOnly);
        JPanel p2 = new JPanel();
        p2.setLayout(new GridLayout(0, 1));
        p2.add(button);
        JFrame frame = new JFrame();
        frame.setTitle("Shaking Button Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(p1, BorderLayout.NORTH);
        frame.add(p2, BorderLayout.SOUTH);
        frame.setSize(240, 160);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private void shakeButton(final boolean shakeWholeButton) {
        final Point point = button.getLocation();
        final Insets margin = button.getMargin();
        final int delay = 75;
        Runnable r = new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 30; i++) {
                    try {
                        if (shakeWholeButton) {
                            moveButton(new Point(point.x + 5, point.y));
                            Thread.sleep(delay);
                            moveButton(point);
                            Thread.sleep(delay);
                            moveButton(new Point(point.x - 5, point.y));
                            Thread.sleep(delay);
                            moveButton(point);
                            Thread.sleep(delay);
                        } else {// text only
                            setButtonMargin(new Insets(margin.top, margin.left + 3, margin.bottom, margin.right - 2));
                            Thread.sleep(delay);
                            setButtonMargin(margin);
                            Thread.sleep(delay);
                            setButtonMargin(new Insets(margin.top, margin.left - 2, margin.bottom, margin.right + 3));
                            Thread.sleep(delay);
                            setButtonMargin(margin);
                            Thread.sleep(delay);
                        }
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        };
        Thread t = new Thread(r);
        t.start();
    }

    private void moveButton(final Point p) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                button.setLocation(p);
            }
        });
    }

    private void setButtonMargin(final Insets margin) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                button.setMargin(margin);
            }
        });
    }
}

EDIT 2nd. with kind hepl by @camickr (look like similair)

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class ShakeComponents1 {

    private JFrame frame = new JFrame();
    private final String items[] = {"One", "Two", "Three"};
    private Timer timer;
    private JPanel panel = new JPanel();
    private JPanel buttonPanel = new JPanel();
    private JButton button = new JButton("  Exit  ");
    private boolean repeats = true;
    private boolean runs = false;
    private Color clr[] = {Color.red, Color.blue, Color.magenta};
    private Insets initMargin;

    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ShakeComponents1().makeUI();
            }
        });
    }

    public void makeUI() {
        buttonPanel = new JPanel();
        buttonPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
        buttonPanel.setLayout(new BorderLayout());
        button.setPreferredSize(new Dimension(100, 45));
        button.setForeground(Color.darkGray);
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent event) {
                Runnable doRun = new Runnable() {

                    @Override
                    public void run() {
                        System.exit(0);
                    }
                };
                SwingUtilities.invokeLater(doRun);
            }
        });
        button.addMouseListener(new java.awt.event.MouseListener() {

            @Override
            public void mouseClicked(MouseEvent e) {
            }

            @Override
            public void mousePressed(MouseEvent e) {
            }

            @Override
            public void mouseReleased(MouseEvent e) {
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                if (runs) {
                    SwingUtilities.invokeLater(new Runnable() {

                        @Override
                        public void run() {
                            runs = false;
                            timer.stop();
                            changePnlBorder(new EmptyBorder(5, 5, 5, 5));
                            changeBtnForegroung(Color.darkGray);
                        }
                    });
                }
            }

            @Override
            public void mouseExited(MouseEvent e) {
                if (!runs) {
                    timer.start();
                    runs = true;
                }
            }
        });
        buttonPanel.add(button);
        final Insets margin = button.getMargin();
        panel.add(buttonPanel);
        for (int i = 0; i < 2; i++) {
            JComboBox combo = new JComboBox(items);
            combo.setMinimumSize(new Dimension(50, 25));
            combo.setMaximumSize(new Dimension(150, 25));
            combo.setPreferredSize(new Dimension(100, 25));
            combo.addActionListener(new ShakeAction());
            panel.add(combo);
        }
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(panel);
        frame.pack();
        frame.setLocation(50, 50);
        frame.setVisible(true);
        timer = new Timer(500, new ShakeAction());
        timer.setRepeats(repeats);
        initMargin = button.getMargin();
    }

    private class ShakeAction extends AbstractAction {

        private static final long serialVersionUID = 1L;
        private int noColor = 0;
        private Border border;
        private int count = 0;

        @Override
        public void actionPerformed(ActionEvent e) {
            timer.start();
            if (count > 5) {
                new Thread(new Runnable() {

                    @Override
                    public void run() {
                        try {
                            Thread.sleep(750);
                            changeBtnForegroung(Color.darkGray);
                            Thread.sleep(750);
                            count = 0;
                            Thread.sleep(750);
                        } catch (Exception e) {
                            System.out.println(e);
                        }
                    }
                }).start();
            } else {
                new Thread(new Runnable() {

                    @Override
                    public void run() {
                        try {
                            runs = true;
                            if (noColor < 2) {
                                noColor++;
                                changeBtnForegroung(clr[noColor]);
                            } else {
                                noColor = 0;
                                changeBtnForegroung(clr[noColor]);
                            }
                            changeBtnMargin(new Insets(initMargin.top, initMargin.left + 10, initMargin.bottom, initMargin.right - 10));
                            border = new EmptyBorder(0, 5, 10, 5);
                            changePnlBorder(border);
                            Thread.sleep(100);
                            changeBtnMargin(new Insets(initMargin.top, initMargin.left - 10, initMargin.bottom, initMargin.right + 10));
                            border = new EmptyBorder(0, 0, 10, 10);
                            changePnlBorder(border);
                            Thread.sleep(100);
                            changeBtnMargin(new Insets(initMargin.top, initMargin.left + 10, initMargin.bottom, initMargin.right - 10));
                            border = new EmptyBorder(5, 10, 5, 0);
                            changePnlBorder(border);
                            Thread.sleep(100);
                            changeBtnMargin(new Insets(initMargin.top, initMargin.left - 10, initMargin.bottom, initMargin.right + 10));
                            border = new EmptyBorder(10, 10, 0, 0);
                            changePnlBorder(border);
                            Thread.sleep(100);
                            changeBtnMargin(new Insets(initMargin.top, initMargin.left, initMargin.bottom, initMargin.right));
                            border = new EmptyBorder(5, 5, 5, 5);
                            changePnlBorder(border);
                            Thread.sleep(100);
                            count++;
                        } catch (Exception e) {
                            System.out.println(e);
                        }
                    }
                }).start();
            }
        }
    }

    private void changePnlBorder(final Border b) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                buttonPanel.setBorder(b);
                buttonPanel.revalidate();
                buttonPanel.repaint();
            }
        });
    }

    private void changeBtnForegroung(final Color c) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                button.setForeground(c);
            }
        });
    }

    private void changeBtnMargin(final Insets margin) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                button.setMargin(margin);
            }
        });
    }
}

EDIT 3rd.

import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;

public class DelayedComboBoxTest extends JFrame {

    private static final long serialVersionUID = 1L;
    private JCheckBox chkA = new JCheckBox("A");
    private JCheckBox chkB = new JCheckBox("B");
    private JCheckBox chkC = new JCheckBox("C");
    private JComboBox cboItems = new JComboBox();

    public DelayedComboBoxTest() {
        super("Delayed ComboBox Test");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        JPanel p = new JPanel();
        p.add(chkA);
        p.add(chkB);
        p.add(chkC);
        p.add(cboItems);
        Container c = getContentPane();
        c.setLayout(new BorderLayout());
        c.add(p);
        pack();
        cboItems.addPopupMenuListener(new MyPopupMenuListener());
    }

    private void rebuildList() {
        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        Vector<String> items = new Vector<String>();
        if (chkA.isSelected()) {
            items.add("A");
        }
        if (chkB.isSelected()) {
            items.add("B");
        }
        if (chkC.isSelected()) {
            items.add("C");
        }
        cboItems.setModel(new DefaultComboBoxModel(items));
        try {
            new Thread().sleep(2500); // simulate a long transaction
        } catch (InterruptedException ex) {
        }
        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
    }

    public static void main(String[] args) {
        JFrame f = new DelayedComboBoxTest();
        f.setVisible(true);
    }

    private class MyPopupMenuListener implements PopupMenuListener {

        @Override
        public void popupMenuCanceled(PopupMenuEvent e) {
        }

        @Override
        public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
        }

        @Override
        public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
            int items = cboItems.getItemCount();
            rebuildList();

            if (items != cboItems.getItemCount()) {
                cboItems.hidePopup();
                cboItems.showPopup();
            }
        }
    }
}

but for all examples there must EDT exist and with Events in the EventQueue otherwise simple doesn't works

Sublimity answered 16/9, 2011 at 9:19 Comment(2)
+2 for Great tips and -1 for some typos (just kidding).Sinuate
hmmm yes I have problem with speaking languages English and Deutch too :-) ,Sublimity
G
4

You should update your list in a separate thread otherwise you end up blocking the event dispatch thread.

Try the following:

final DefaultListModel model = new DefaultListModel();
final JList list = new JList(model);

//another thread to update the model
final Thread updater = new Thread() {
    /* (non-Javadoc)
     * @see java.lang.Thread#run()
     */
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            model.addElement(i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
};
updater.start();
Genna answered 16/9, 2011 at 9:18 Comment(8)
I still think that model.addElement(i) must be wrapped into invokeLater, please update your postSublimity
@Sublimity really? I am updating the model, which will in turn fire an event to a handler which will call repaint on the list. I believe this repaint call will queue a request for the event-dispatching thread to call paint, so it should be safe.Genna
true is that there are no updates on EDT, all are done past Thread.sleep(1000);, because all fireXxxXxx are out of EDTSublimity
I'll edit my post with examples for programaticaly block EDT with Thread.sleep(int) for correct and expected output to the GUISublimity
@Sublimity in my code, the model is updated out of the EDT, but the repaint calls which are performed by the model listeners are performed on the EDT. If you run my code, you will see that it produces the right output.Genna
in due all respect to your person, you are excelent Java coder, with clear and fast mind, but repaint (I know that alive EDT, in all cases) is for GUI hardiest methods as there exists, for your contributing here +1 by my person for answer (even was accepted) big -1Sublimity
-1 model updates must happen on the EDT (as @Sublimity already noted)Canonry
@Sublimity and kelopatra, very thanks to you both, it is a very finer level thing, which I was searching for.. Thanks much again..Jovitajovitah
V
1

This code explains how to insert values in Swing JList from a resultset in java. Make changes as per your requirements. hope this will help you.

try
    {
        CreateConnection();
        st=con.prepareStatement(QueryString);
        rs=st.executeQuery();
        int i = 0;  
        rs.last(); 
        final String[] strings = new String[rs.getRow()]; 
        rs.first();
        strings[i]="Send to All";i++;
        while (rs.next()) {  
          strings[i] = rs.getString(1); i++; 
        } 
        ToBeFilled.setModel(new javax.swing.AbstractListModel() {

        public int getSize() { return strings.length; }
        public Object getElementAt(int i) { return strings[i]; }
        });
        con.close();
    }
    catch(Exception ex)
    {    
        JOptionPane.showMessageDialog(null, ex.toString());
    }

Or Just Simple Code to Insert values

jList1.setModel(new javax.swing.AbstractListModel() {
String[] strings = { "Send to All", "ABC", "DEF" };
public int getSize() { return strings.length; }
public Object getElementAt(int i) { return strings[i]; }

});

Remember to add this code in after initComponents() at the top of the page.

Vidicon answered 19/1, 2013 at 15:43 Comment(1)
Instead of rs.first(); you have to use rs.beforeFirst();. Otherwise you will miss the first record.Settler
H
-1
final DefaultListModel model = new DefaultListModel();


    final Thread updater = new Thread() {

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                model.addElement(i);
                listData.setModel(model);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    };
    updater.start();
Hamill answered 31/10, 2013 at 15:2 Comment(1)
no, that's wrong: you must not access swing components off the EDT. And why are you basically copying the accepted (though incorrect) answer? re-setting the model after each insert improves exactly .. nothing of the basic error.Canonry

© 2022 - 2024 — McMap. All rights reserved.