3

This might be a stupid question, but I'm having trouble thinking this through.

I wrote a method that uses a LinkedList to move through loaded MIDI instruments. I want to make a next and a previous button so that every time you click the button you traverse through the LinkedList.

If I hardcode itr.next(); or itr.previous(); multiple times I can traverse through the LinkedList

public void setInsturment(Synthesizer start,MidiChannel currentChannel[])
{
    try
    {
        start.open();

        Soundbank bank = start.getDefaultSoundbank();

        start.loadAllInstruments(bank);

        LinkedList<Instrument> currentInstrument = new LinkedList<Instrument>();

        Instrument instrs[] = start.getLoadedInstruments();

        currentInstrument.add(instrs[0]);
        currentInstrument.add(instrs[1]);
        currentInstrument.add(instrs[2]);
        currentInstrument.add(instrs[3]);
        currentInstrument.add(instrs[4]);

        ListIterator itr = currentInstrument.listIterator();
        itr.next();
        itr.next();
        itr.next();
     // nextInstrument();

        currentChannel[1].programChange(0,itr.nextIndex());

    }

    catch(MidiUnavailableException e)
    {
        System.out.print("error");
    }

}

I'm having a lot of trouble making a button that can traverse through the list. Is there an efficient way to do this? I tried something like this with no success.

public void actionPerformed(ActionEvent e)
{
    if (e.getSource() == nextButton)
    {
        sound.nextInstrument();
    }

public void nextInstrument()
{
    itr.next();
}

Thanks in advance guys!

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Brian P
  • 356
  • 2
  • 11
  • Why a linked list? An ArrayList and remembering the current index seems easier (especially since you already have your instruments in an array). – Thilo Apr 24 '12 at 02:02
  • I needed to use a data structure and I'm familiar with linked lists, however I didnt know Java had ArrayLists. – Brian P Apr 24 '12 at 02:10

4 Answers4

4

The ListIterator#next() method returns the object of interest. If it were my project, I'd assign what is returned from that method to a class field and then notify the GUI of the change.

someInstrument = itr.next();
// fire notify observers method.
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • 1
    I'd just use an array for this and dump it in a component that can handle the next/previous, rendering and notification of `Instrument` change. See my example. – Andrew Thompson Apr 24 '12 at 02:35
4

Well, hmm, a linked list is a List and its items can be accessed by index, this is not the optimal structure to access items by index but I really don't know if you can have a cursor on that kind of collection but you can store the current index on an instance variable.

If you really want random access, then you should consider using ArrayList instead of linked list.

Example:

class NextPrevList {
    private int index = 0;
    private List currentList; //initialize it with some list

    public Object next() {
        return list.get(++index);
    }
    public Object prev() {
        //maybe add a check for out of bounds
        if (index == 0) return null;
        return list.get(--index);
    }
}

Personally I think it would be more performant with an ArrayList rather than a LinkedList

  • 1
    +1 for using the index of the list. Problem with the iterator approach is that you cannot add/remove any instruments while your UI is open, or you are screwed (wouldn't be the first person to bump into a `ConcurrentModificationException`) – Robin Apr 24 '12 at 05:40
4

Code to the interface: List<Instrument>. This related example navigates a List<ImageIcon>, but the implementation could be changed as required.

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • I'd just use an array for this. See my example. – Andrew Thompson Apr 24 '12 at 02:33
  • 1
    +1 for using the index of the list. Problem with the iterator approach is that you cannot add/remove any instruments while your UI is open, or you are screwed (wouldn't be the first person to bump into a `ConcurrentModificationException`) – Robin Apr 24 '12 at 05:40
4

MIDI instruments .. next and a previous button

Use an array (e.g. Instrument[]). It might be displayed in a JComboBox, a JList or a JSpinner to allow the user to select an instrument. Here is an example using a combo with renderer.

enter image description here

import java.awt.Component;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
import javax.swing.*;
import javax.sound.midi.*;

class InstrumentSelector {

    public static void main(String[] args) throws MidiUnavailableException {
        Synthesizer synthesizer = MidiSystem.getSynthesizer();
        synthesizer.open();
        final Instrument[] orchestra = synthesizer.getAvailableInstruments();
        SwingUtilities.invokeLater(new Runnable(){
            public void run() {
                JComboBox orchestraSelector = new JComboBox(orchestra);
                orchestraSelector.setRenderer(new InstrumentRenderer());

                JOptionPane.showMessageDialog(null, orchestraSelector);
            }
        });
    }
}

class InstrumentRenderer extends BasicComboBoxRenderer {

    @Override
    public Component getListCellRendererComponent(
        JList list,
        Object value,
        int index,
        boolean isSelected,
        boolean cellHasFocus) {
        Component c = super.getListCellRendererComponent(
            list, value, index, isSelected, cellHasFocus);
        if (c instanceof JLabel && value instanceof Instrument) {
            JLabel l = (JLabel)c;
            Instrument i = (Instrument)value;
            l.setText(i.getName());
        }
        return c;
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433