2013-09-01 4 views
0

내 최종 목표는 사용자가 요소를 앞뒤로 이동할 수있는 두 개의 JList 사이를 유지하는 것입니다. 요소가 사전 순으로 삽입되도록 TreeSet을 사용하고 있습니다. 여기에 시각적 표현입니다 :ListModel을 사용하여 TreeSet을 음영 처리

enter image description here

아래있는 SSCCE에, 지금까지 내 코드입니다. 대부분 효과가 있지만 때로는 ArrayOutOfBoundsException이 나옵니다. 문제는 프로그램이 실제로 존재하는 것보다 더 많은 요소가 선택되었다고 생각하는 것과 관련이 있습니다. 문제를 재현하는 한 가지 방법은 왼쪽에있는 두 개의 요소를 선택한 다음 오른쪽 버튼을 두 번 누르면됩니다.

import java.awt.Dimension; 
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 DefaultListModel<String> { 
     private TreeSet<String> model = new TreeSet<String>(); 

     public StringListModel() { 
     } 

     public StringListModel(List<String> Strings) { 
      addAll(Strings); 
     } 

     public int getSize() { 
      return model.size(); 
     } 

     public String getElementAt(int index) { 
      return (String) model.toArray()[index]; 
     } 

     public void add(String String) { 
      if (model.add(String)) { 
       fireContentsChanged(this, 0, getSize()); 
      } 
     } 

     public void addAll(List<String> quets) { 
      for (String String : quets) { 
       model.add(String); 
      } 

      fireContentsChanged(this, 0, getSize()); 
     } 

     public void clear() { 
      model.clear(); 
      fireContentsChanged(this, 0, getSize()); 
     } 

     public boolean contains(Object element) { 
      return model.contains(element); 
     } 

     public String firstElement() { 
      return model.first(); 
     } 

     public Iterator iterator() { 
      return model.iterator(); 
     } 

     public String lastElement() { 
      return model.last(); 
     } 

     public void removeAll(Collection<?> elements) { 
      for (Object element : elements) { 
       removeElement(element); 
      } 

      fireContentsChanged(this, 0, getSize()); 
     } 

     public boolean removeElement(Object element) { 
      boolean removed = model.remove(element); 
      if (removed) { 
       fireContentsChanged(this, 0, getSize()); 
      } 

      return removed; 
     } 
    } 

    public static void main(String[] args) { 
     new GUI().setVisible(true); 
    } 
} 
+1

를 호출하지만 당신은'StringListModel'이 완전히 잘못된 것입니다 수 있도록 할 것입니다. 'DefaultListModel'에서 확장하면 add/remove/... 메소드를 사용해야합니다. 귀하의 경우 직접 인터페이스를 구현하거나 'AbstractListModel'에서 확장하는 것이 좋습니다. – Robin

+0

AbstractListModel에서 동일한 문제가 발생했습니다. –

답변

1

당신이 모델의 선택을 취소 귀하의 actionPerformed를 수정하면 더 이상 ArrayOutOfBoundsException가 없습니다 :

@Override 
    public void actionPerformed(ActionEvent e) { 
     button = (JButton) e.getSource(); 

     if (button.equals(leftButton)) { 
      removeFromQueue(); 
      **queue.getSelectionModel().clearSelection();** 
     } else if (button.equals(rightButton)) { 
      addToQueue(); 
      **list.getSelectionModel().clearSelection();** 
     } 
    } 
+0

기본'ListModel'이 올바른 변경 사항을 발생시키는 경우에는 필요하지 않습니다 (예 :'remove' 이벤트에서 자동으로 선택 항목에서 사라짐). – Robin

+0

예, 맞습니다. OP의 StringListModel을 어떻게 수정해야합니까? 명시 적으로 선택을 지울 때만 작동하도록 할 수 있습니다. 그것을 답으로 추가하면 투표 할 것이지만 다시는 명시 적 호출 없이는 작동하지 않을 것입니다. – ditkin

+0

좋은 답변입니다! 고맙습니다! 로빈, 너의 제안을보고 싶네. –

2

이 구현이 작동하는 것 같다합니다. TreeSet을 간단한 List으로 변경했습니다. 단점은 삽입/제거가 약간 느려지지만 최소한 정확한 이벤트를 발생시킬 수 있다는 것입니다. UI 위젯의 경우처럼 기본 모델이 결코 거대하지 않을 수도 있고 (또는 UI가 사용 불능이 될 수 있으므로) 이것이 허용 가능하다고 생각합니다.

나는 AbstractListModel에서 확장되었지만 DefaultListModel까지 확장 할 수도 있습니다. 이 경우 당신은 아마 addElement 방법은 올바른 인덱스를 계산하고 내가 상세하게 체크하지 않은 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); 
     } 
    }); 

    } 
}