2012-07-11 92 views
2

我想在JList中显示HashSet的内容。我用下面的语句来实现这一点:现在在JList中显示HashSet并实时更新项目

JList list = new JList(hashset.toArray()); 

,我想list以反映hashset的变化。我可以通过调用setListData()hashset的元素改变,如下做到这一点:

list.setListData(hashset.toArray()); 

这似乎不是要去做一个正确的方法。正如我从tutorial所理解的那样,我需要扩展/实施ListModel。如果它适用于我的意图,请提供重载ListModel的适当示例。否则,请提出一个更好的方法来解决这个问题。

在此先感谢。

+1

编辑:我也将扩展[AbstractListModel上](http://docs.oracle.com/javase/7/docs/api/javax/swing /AbstractListModel.html)类,而不是单独使用[ListModel](http://docs.oracle.com/javase/7/docs/api/javax/swing/ListModel.html)接口。这将允许你使用'fireXXX(...)'方法来通知任何监听者数据是否改变。 – 2012-07-11 16:46:41

+0

@HovercraftFullOfEels感谢您的回复。 :)我可能会使用TreeSet。至于试图自己实现一个ListModel - 我确实尝试过。我无法弄清楚如何封装一个Set,以及如何处理ListDataListeners。 – Vlad 2012-07-11 16:47:13

+0

它必须严格是'HashSet',或者只是具有相似功能和性能特征的东西? – 2012-07-11 18:27:35

回答

1

根据我们在聊天中的讨论,这里有一个可能的解决方案。我还没有调试也不测试这一点,所以买者自负:

import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import java.util.Comparator; 
import java.util.Iterator; 
import java.util.TreeSet; 

import javax.swing.*; 

public class TreeSetInJListTest extends JPanel { 
    private static final long serialVersionUID = 1L; 
    private static final String[] DATA_ARRAY = { "one", "two", "three", "two", 
     "three", "this is a longer string" }; 
    TreeSetListModel<String> stringListModel = new TreeSetListModel<String>(
     String.CASE_INSENSITIVE_ORDER); 
    JList<String> jList = new JList<String>(stringListModel); 

    public TreeSetInJListTest() { 
     for (int i = 0; i < DATA_ARRAY.length; i++) { 
     stringListModel.add(DATA_ARRAY[i]); 
     } 

     add(new JScrollPane(jList)); 
     add(new JButton(new AddToListAction("Add To List", KeyEvent.VK_A))); 
    } 

    @SuppressWarnings("serial") 
    private class AddToListAction extends AbstractAction { 
     public AddToListAction(String name, int mnemonic) { 
     super(name); 
     putValue(MNEMONIC_KEY, mnemonic); 
     } 

     @Override 
     public void actionPerformed(ActionEvent arg0) { 
     String element = JOptionPane.showInputDialog(TreeSetInJListTest.this, 
       "Enter String:", "Insert Text Into JList", 
       JOptionPane.OK_CANCEL_OPTION); 
     stringListModel.add(element); 
     } 
    } 

    private static void createAndShowGui() { 
     TreeSetInJListTest mainPanel = new TreeSetInJListTest(); 

     JFrame frame = new JFrame("Example"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

class TreeSetListModel<T extends Comparable<T>> extends AbstractListModel<T> { 
    private static final long serialVersionUID = 1L; 
    private TreeSet<T> treeSet; 

    public TreeSetListModel() { 
     treeSet = new TreeSet<T>(); 
    } 

    public TreeSetListModel(Comparator<? super T> comparator) { 
     treeSet = new TreeSet<T>(comparator); 
    } 

    @Override 
    public T getElementAt(int index) { 
     if (index < 0 || index >= getSize()) { 
     String s = "index, " + index + ", is out of bounds for getSize() = " 
       + getSize(); 
     throw new IllegalArgumentException(s); 
     } 
     Iterator<T> iterator = treeSet.iterator(); 
     int count = 0; 
     while (iterator.hasNext()) { 
     T t = (T) iterator.next(); 
     if (index == count) { 
      return t; 
     } 
     count++; 
     } 
     // out of index. return null. will probably never reach this 
     return null; 
    } 

    @Override 
    public int getSize() { 
     return treeSet.size(); 
    } 

    public int getIndexOf(T t) { 
     int index = 0; 
     for (T treeItem : treeSet) { 
     if (treeItem.equals(treeItem)) { 
      return index; 
     } 
     index++; 
     } 
     return -1; 
    } 

    public boolean add(T t) { 
     boolean result = treeSet.add(t); 
     if (result) { 
     int index = getIndexOf(t); 
     fireIntervalAdded(this, index, index + 1); 
     } 
     return result; 
    } 

    public boolean remove(T t) { 
     int index = getIndexOf(t); 
     if (index < 0) { 
     return false; 
     } 
     boolean result = treeSet.remove(t); 
     fireIntervalRemoved(this, index, index + 1); 
     return result; 
    } 

} 
+0

非常感谢您的帮助!我有类似的东西。 :)我为模型创建了一个非模板类,并为该模型的构造函数提供了一个匿名Comparator。没有实现getIndexOf(),而是使用了fireIntervalAdded(Object,0,set.size());正如我们前面所讨论的,我可能需要访问GUI类之外的模型。我会为它创建一个访问器吗?其余的似乎被排序。再次感谢。 – Vlad 2012-07-11 18:49:24

+1

@Vlad:是的,你可以为它创建一个访问器,但是我一定会返回TreeSet的一个*副本,而不是原始的集合,以防止原始集合被改变。 – 2012-07-11 18:55:53

+0

我的意思是访问模型,因为我需要在GUI之外使用add()。 :)至于TreeSet,如果我需要返回,我猜'Collections.unmodifiableSet(set);'会工作吗? – Vlad 2012-07-11 19:00:54