1

My use case is that a List<String> is passed to a Jpanel and for each String in the List, the JPanel renders a UI component. This UI component consists of 3 buttons and my current code for my given use case is as follows. --
The code for the 'UI component' follows --

public class MacroEditorEntity implements ActionListener {
    private String macro;
    private JButton upButton;
    private JButton downButton;
    private JButton MacroDetailsButton;

    public MacroEditorEntity(String macro) {
    this.macro = macro;
    upButton =  new JButton("Up");
    downButton = new JButton("Down");
    MacroDetailsButton =  new JButton(macro);

    upButton.addActionListener(this);
    downButton.addActionListener(this);
    MacroDetailsButton.addActionListener(this);
}

    @Override
    public void actionPerformed(ActionEvent evt) {

        if(evt.getSource().equals(MacroDetailsButton))
        {
            System.out.println(macro);
        }
    }

    public JButton GetUpButton()
    {
        return upButton;
    }
    public JButton GetDownButton()
    {
        return downButton;
    }
    public JButton getMacroDetailsButton()
    {
        return MacroDetailsButton;
    }
}

The code for my Panel is as follows --

public class MacroEditor extends JPanel implements PropertyChangeListener {

    private static final long serialVersionUID = 1L;
    private List<String> stringlist;

    public MacroEditor(List<String> list) {

        this.stringlist = list;
        setupComponents();
        validate();
        setVisible(true);
    }

    public void setupComponents()
    {
        Box allButtons =  Box.createVerticalBox();
        for(String string : stringlist)
        {
            MacroEditorEntity entry =  new MacroEditorEntity(string);
            Box entryBox =  Box.createHorizontalBox();
            entryBox.add(entry.GetUpButton());
            entryBox.add(Box.createHorizontalStrut(15));
            entryBox.add(entry.getMacroDetailsButton());
            entryBox.add(Box.createHorizontalStrut(15));
            entryBox.add(entry.GetDownButton());

            allButtons.add(entryBox);
        }

        add(allButtons);
    }

    @Override
    public void propertyChange(PropertyChangeEvent arg0) {
        revalidate();
        repaint();
    }

}

The code works fine for all Strings in the passed List. I want my Panel to pick up any change that may happen to the List like additions or deletions and add/remove relevant corresponding UI components accordingly. I think this can be done by using PropertyChangeListener but have not been able to account for that in my code.
Any ideas or suggestions on how i can make my Panel render/rerender stuff as soon as there are changes to the List would be of help.

Simon
  • 9,255
  • 4
  • 37
  • 54
ping
  • 1,229
  • 3
  • 21
  • 41

1 Answers1

2

What you need here is an observable collection. This should do it: http://commons.apache.org/dormant/events/apidocs/org/apache/commons/events/observable/ObservableCollection.html

Edit:

Here's the code snippet you requested:

public class ObservableListExample implements StandardPostModificationListener,
    StandardPreModificationListener {

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

    public ObservableListExample() {

        ObservableList list = ObservableList.decorate(new ArrayList<>(),
                new StandardModificationHandler());

        list.getHandler().addPostModificationListener(this);
        list.getHandler().addPreModificationListener(this);
        //....

    }

    @Override
    public void modificationOccurring(StandardPreModificationEvent event) {
        // before modification
        Collection changeCollection = event.getChangeCollection();
        if (event.isTypeAdd()) {
            // changeCollection contains added elements
        } else if (event.isTypeReduce()) {
            // changeCollection contains removed elements
        }
    }

    @Override
    public void modificationOccurred(StandardPostModificationEvent event) {
        // after modification
        Collection changeCollection = event.getChangeCollection();
        if (event.isTypeAdd()) {
            // changeCollection contains added elements
        } else if (event.isTypeReduce()) {
            // changeCollection contains removed elements
        }
    }
}

By the way: Another concept that helps to bind buisness objects to your GUI and react to modifications (bidirectionally) is Data Binding. Have a look at this, a Data Binding Library commonly used with Swing.

Simon
  • 9,255
  • 4
  • 37
  • 54
  • 1
    perfect, I didn't realize this class existed and was writing it in an answer. Thanks! – vextorspace Mar 17 '12 at 20:55
  • @Simon -- Thanks for your answer. I went through the javadoc and am have a fair understanding of the Observer pattern. Im not entirely sure how the ObservableCollection would tie into my code. Would i not require a PropertyChangeListener then ? Pardon my ignorance but a code snippet of how to use ObservableCollection and how it would tie into my code would help me to understand better. – ping Mar 17 '12 at 22:20
  • @Simon -- Thanks. Im accepting this as the answer. Again, Thanks for your help ! – ping Mar 18 '12 at 12:36