3

I've got some very old code which uses a Box to list some information. I create it like so:

Box patterns = Box.createVerticalBox();

Very (very) often, new items are added and old items are removed eg:

label = new JLabel("xyz");
patterns.add(label);

and later

patterns.remove(label);

whenever something is added ore removed I have to have it repaint, so I call:

patterns.revalidate();
patterns.repaint();

Problem is, since this happens very often it chokes up the UI. I think I need a better implementation in order to make it more efficient.

I know I could maintain a list of the active items in the background and then intermittently update the actual UI (batch update) but...

Can someone suggest a more efficient alternative approach?

mKorbel
  • 109,525
  • 20
  • 134
  • 319
pstanton
  • 35,033
  • 24
  • 126
  • 168

2 Answers2

6

Why don't you just use a JList and implement a cell renderer?

Or more flexibility with a JTable and implement a table cell renderer (returns a Component instead)?

Yanick Rochon
  • 51,409
  • 25
  • 133
  • 214
  • I have changed to using a `JList` + `DefaultListModel` and extended `DefaultListCellRenderer`, stamping the JLabel it produces. Is about 1000 * as efficient. Thx. – pstanton Jul 07 '11 at 04:33
  • 1
    @pstanton JList and JTable returns JLabel by default @Yanick Rochon +1 – mKorbel Jul 07 '11 at 05:56
  • @mKorbel: Excellent point about [default cell renderers](http://download.oracle.com/javase/tutorial/uiswing/components/table.html#editrender). – trashgod Jul 07 '11 at 13:18
  • @pstanton, indeed! The `DefaultListCellRenderer` and `DefaultTableCellRenderer` classes extend `JLabel`, thank you for the precision! – Yanick Rochon Jul 07 '11 at 13:54
  • yes, possibly the biggest performance enhancement is the 'stamping' approach used by JList and JTable. making use of that here is probably what gave me most of the improvement. – pstanton Jul 17 '11 at 05:01
  • For reference, `JTable` renderers and editors are a good example of the [flyweight pattern](http://en.wikipedia.org/wiki/Flyweight_pattern). – trashgod Sep 06 '11 at 10:06
3

Based on this example, the following code loafs doing 16 labels at 10 Hz.

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;

/** @see https://stackoverflow.com/questions/6605554 */
public class ImageLabelPanel extends Box implements ActionListener {

    private static final int N = 16;
    private final List<JLabel> list = new ArrayList<JLabel>();
    private final Timer timer = new Timer(100, this);

    ImageLabelPanel() {
        super(BoxLayout.Y_AXIS);
        BufferedImage bi = null;
        try {
            bi = ImageIO.read(new File("image.jpg"));
        } catch (IOException e) {
            e.printStackTrace(System.err);
        }
        for (int r = 0; r < N; r++) {
            int w = bi.getWidth();
            int h = bi.getHeight() / N;
            BufferedImage b = bi.getSubimage(0, r * h, w, h);
            list.add(new JLabel(new ImageIcon(b)));
        }
        createPane();
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setVisible(true);
        timer.start();
    }

    private void createPane() {
        this.removeAll();
        for (JLabel label : list) {
            add(label);
        }
        this.revalidate();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Collections.shuffle(list);
        createPane();
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ImageLabelPanel();
            }
        });
    }
}
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045