日期:2014-05-20  浏览次数:20826 次

JComboBox Model過濾數據
Java code

import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.PlainDocument;

public class FilterJComboBox extends JComboBox{
    
    private FilterJComboBox self;
//    private UpperCaseDocument upperCaseDocument;
    private MyDocumentListener documentListener;
    private JTextField jtf;
    private String[] listItems ;
     
    public static void main(String...args){
        JFrame frame = new JFrame("FilterJComboBoxTest");
        FilterJComboBox filterComboBox = new FilterJComboBox();
        frame.getContentPane().add(filterComboBox);
        frame.setVisible(true);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
//        BasicComboBoxEditor b; 
    }
    
    public FilterJComboBox(){
        super();
        self = this;
        this.setEditable(true);
        this.setModel(new FilterModel());
        jtf = (JTextField)this.getEditor().getEditorComponent();
//        upperCaseDocument = new UpperCaseDocument(jtf);
//        upperCaseDocument.SetOnlyFirstLetterCapitalize(true);
        documentListener = new MyDocumentListener();
        
io


在調用refilter的時候會報錯,Attempt to mutate in notification。請問怎麼解決?
我想實現的功能就是:當用戶鍵入首字母時,從model中過濾出符合條件的數據。
不要用KeyListener,那樣效率太低了

------解决方案--------------------
出错的位置在AbsractDocument,也就是所有document的基类中,一个writeLock方法。读一下注释和代码:
原因在于在处理修改的事件中,你又要再次修改,从而导致再次触发修改。无论直接还是间接,这都是不允许的,一次也不允许。
至于你的想法,你得说的详细点。我敲键盘,打了一个a,这个时候你的编辑区域,是出现什么?选中的那个吗?如果是选中的,那么必须修改编辑区域,这就导致再次修改。即使你调用的是jcombobox的方法,但只要选中项改变(你的remove。insert操作都会触发这个操作),就会使得编辑区域的值再次改变。

尽管也许你经过有限的步数之后会终止,不会无限的循环操作下去,但是,如之前所言。不允许。
所以,请调整你的思路,明白事件的限制,明白那些可做,那些不行,再进行设计,不然,一些东西,很可能无法实现,即使,勉强实现了,也有许多的漏洞。倒不如,从一开始就寻求一种可以接受的替代方法。

一家之言,仅供参考交流。


Java code

 protected synchronized final void writeLock() {
    try {
        while ((numReaders > 0) || (currWriter != null)) {
        if (Thread.currentThread() == currWriter) {
                    if (notifyingListeners) {
                        // Assuming one doesn't do something wrong in a
                        // subclass this should only happen if a
                        // DocumentListener tries to mutate the document.
                        throw new IllegalStateException(
                                      "Attempt to mutate in notification");
                    }
                    numWriters++;
                    return;
                }
        wait();
        }
        currWriter = Thread.currentThread();
            numWriters = 1;
    } catch (InterruptedException e) {
        throw new Error("Interrupted attempt to aquire write lock");
    }
    }