This implementation seems to work. Note that I changed the TreeSet
to a simple List
. Drawback is that the insertion/removal will be a bit slower, but at least I can fire the correct events. Seeing as it is for a UI widget, I think this is acceptable as the underlying model will never be gigantic (or the UI would become unusable).
I extended from AbstractListModel
but you could also extend from DefaultListModel
. In that case you would probably want to ensure that the addElement
method calculates the correct index and calls super.add( calculatedIndex, element)
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import javax.swing.*;
public class GUI extends JFrame {
private GridBagLayout gridBag = new GridBagLayout();
private static final String[] ALL_STRINGS = {"B", "A", "C"};
private JButton leftButton = new JButton( "<" );
private JButton rightButton = new JButton( ">" );
private StringListModel listModel = new StringListModel( Arrays.asList( ALL_STRINGS ) );
private StringListModel queueModel = new StringListModel();
private JList<String> list = new JList<String>( listModel );
private JList<String> queue = new JList<String>( queueModel );
public GUI() {
setWindowProperties();
addComponents();
}
private void setWindowProperties() {
setLayout( gridBag );
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
setSize( new Dimension( 300, 200 ) );
setTitle( "JList, ListModel, and TreeSet" );
setResizable( false );
setLocationRelativeTo( null );
}
private void addComponents() {
leftButton.addActionListener( new QueueListener() );
rightButton.addActionListener( new QueueListener() );
JScrollPane listScroll = new JScrollPane( list );
JScrollPane queueScroll = new JScrollPane( queue );
Dimension scrollSize = new Dimension( 50, 100 );
listScroll.setPreferredSize( scrollSize );
queueScroll.setPreferredSize( scrollSize );
add( listScroll );
add( leftButton );
add( rightButton );
add( queueScroll );
}
private class QueueListener implements ActionListener {
private JButton button;
@Override
public void actionPerformed( ActionEvent e ) {
button = ( JButton ) e.getSource();
if ( button.equals( leftButton ) ) {
removeFromQueue();
}
else if ( button.equals( rightButton ) ) {
addToQueue();
}
}
private void removeFromQueue() {
List<String> Strings = queue.getSelectedValuesList();
queueModel.removeAll( Strings );
listModel.addAll( Strings );
}
private void addToQueue() {
List<String> Strings = list.getSelectedValuesList();
listModel.removeAll( Strings );
queueModel.addAll( Strings );
}
}
private class StringListModel extends AbstractListModel<String> {
private List<String> model = new ArrayList<>();
public StringListModel() {
}
public StringListModel( List<String> strings ) {
addAll( strings );
}
@Override
public int getSize() {
return model.size();
}
@Override
public String getElementAt( int index ) {
return model.toArray( new String[model.size()])[index];
}
public void addAll( Collection<String> strings ){
for ( String string : strings ) {
add( string );
}
}
public void add( String string ){
int index = calculateIndex( string );
model.add( index, string );
fireIntervalAdded( this, index, index );
}
public void remove( String string ){
int index = model.indexOf( string );
if ( index != -1 ){
model.remove( index );
fireIntervalRemoved( this, index, index );
}
}
public void removeAll( Collection<String> strings ){
for ( String next : strings ) {
remove( next );
}
}
private int calculateIndex( String input ){
if ( model.size() == 0 ){
return 0;
}
int index = 0;
while ( model.get( index ).compareTo( input ) <=0 ){
index++;
if ( index == model.size() ){
return index;
}
}
return index;
}
}
public static void main( String[] args ) {
EventQueue.invokeLater( new Runnable() {
@Override
public void run() {
new GUI().setVisible( true );
}
} );
}
}