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) {
    }
}
Akhil K Nambiar
  • 3,835
  • 13
  • 47
  • 85

4 Answers4

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

mKorbel
  • 109,525
  • 20
  • 134
  • 319
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();
dogbane
  • 266,786
  • 75
  • 396
  • 414
  • 1
    I still think that `model.addElement(i)` must be wrapped into `invokeLater`, please update your post – mKorbel Sep 16 '11 at 09:20
  • @mKorbel 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. – dogbane Sep 16 '11 at 09:34
  • 3
    true is that there are no updates on EDT, all are done past Thread.sleep(1000);, because all fireXxxXxx are out of EDT – mKorbel Sep 16 '11 at 09:41
  • I'll edit my post with examples for programaticaly block EDT with Thread.sleep(int) for correct and expected output to the GUI – mKorbel Sep 16 '11 at 09:48
  • @mKorbel 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. – dogbane Sep 16 '11 at 09:51
  • 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 -1 – mKorbel Sep 16 '11 at 10:01
  • 2
    -1 model updates _must_ happen on the EDT (as @mKorbel already noted) – kleopatra Dec 26 '11 at 12:12
  • @mKorbel and kelopatra, very thanks to you both, it is a very finer level thing, which I was searching for.. Thanks much again.. – pratikabu Jun 07 '13 at 14:26
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.

-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();
  • 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. – kleopatra Oct 31 '13 at 16:07