在Jtable中自动完成JCombobox - 输入编辑器无法正常工作

时间:2013-11-20 15:35:58

标签: java swing autocomplete jtable jcombobox

我正在尝试使用自定义模型在JTable中实现自动完成ComboBox,但事实证明这比我估计的更难。我读到了我能找到的关于这个的所有内容,但无法理解为什么它不起作用。以下是基于https://today.java.net/pub/a/today/2007/07/19/adding-auto-completion-to-swing-comboboxes.html

的示例

我正在使用SwingX的AutoCompleteDecorator。问题是编辑器无法正常工作 - 我无法输入它。我甚至试过添加一个自定义编辑器,虽然在上面的链接上说它不需要它,因为AutoCompleteDecorator会为你处理它。

import java.awt.Component;
import java.util.HashMap;
import javax.swing.ComboBoxEditor;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.plaf.basic.BasicComboBoxEditor;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import org.jdesktop.swingx.JXComboBox;
import org.jdesktop.swingx.autocomplete.AutoCompleteDecorator;
import org.jdesktop.swingx.autocomplete.ObjectToStringConverter;

public class TestComboCellEditor {

    public static void main(String[] args) {

        TestComboCellEditor test = new TestComboCellEditor();
        test.go();
    }

    public void go() {

        //create the frame
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // create and add a tabbed pane to the frame
        JTabbedPane tabbedPane = new JTabbedPane();
        frame.getContentPane().add(tabbedPane);
        //create a table and add it to a scroll pane in a new tab
        final JTable table = new JTable(new DefaultTableModel(new Object[]{"A", "B"}, 5));
        JScrollPane scrollPane = new JScrollPane(table);
        tabbedPane.addTab("test", scrollPane);

        // create a simple JComboBox and set is as table cell editor on column A
        UserRepository rep = new UserRepository();
        UserInfo[] comboElements = rep.getAllUsers();
        JXComboBox comboBox = new JXComboBox(comboElements);
        comboBox.setEditable(true);
        comboBox.setRenderer(new CustomListCellRenderer());
//        comboBox.setEditor(new UserInfoEditor(comboBox.getEditor()));

        // apply autocomplete decorator
        AutoCompleteDecorator.decorate(comboBox, new ObjectToStringConverter() {
            @Override
            public String getPreferredStringForItem(Object item) {
                if (item instanceof UserInfo) {
                    return ((UserInfo) item).getFirstName();
                } else {
                    return null;
                }

            }
        });

        table.getColumn("A").setCellEditor(new DefaultCellEditor(comboBox));
        table.getColumn("A").setCellRenderer(new CustomTableCellRenderer());

        // pack and show frame
        frame.pack();
        frame.setVisible(true);
    }

    public class CustomTableCellRenderer extends DefaultTableCellRenderer {

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            if (value != null) {
                // this is used to extract the data you want to display in the table from your "custom model"
                UserInfo user = (UserInfo) value;
                return super.getTableCellRendererComponent(table, user.getFirstName(), isSelected, hasFocus, row, column);
            } else {
                return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            }
        }
    }

    public class CustomListCellRenderer extends DefaultListCellRenderer {

        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            if (value instanceof UserInfo) {
                JLabel result = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                UserInfo userInfo = (UserInfo) value;
                result.setText(userInfo.getFirstName());
                return result;
            } else {
                return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            }
        }
    }

    public class UserInfo {

        private String firstName;
        private String lastName;

        public UserInfo(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public String getFirstName() {
            return firstName;
        }

        public String getLastName() {
            return lastName;
        }
    }

    public class UserRepository {

        private UserInfo[] comboElements;
        private HashMap<String, UserInfo> objectsMap;

        public UserRepository() {
            comboElements = new UserInfo[5];
            comboElements[0] = new UserInfo("John", "Doe");
            comboElements[1] = new UserInfo("Betty", "Doe");
            comboElements[2] = new UserInfo("Elenor", "Smith");
            comboElements[3] = new UserInfo("Helen", "Kelly");
            comboElements[4] = new UserInfo("Joe", "Black");
            objectsMap = new HashMap<>();
            for (int i = 0; i < 5; i++) {
                objectsMap.put(comboElements[i].getFirstName(), comboElements[i]);
            }
        }

        public UserInfo getUserInfo(String name) {
            return objectsMap.get(name);
        }

        public UserInfo[] getAllUsers() {
            return comboElements;
        }
    }

    public class UserInfoEditor extends BasicComboBoxEditor {

        public UserInfoEditor(ComboBoxEditor origEditor) {
            super();
            editor.setBorder(((JComponent) origEditor.getEditorComponent())
                    .getBorder());
        }

        @Override
        public void setItem(Object anObject) {
            if (anObject instanceof UserInfo) {
                super.setItem(((UserInfo) anObject).getFirstName());
            } else {
                super.setItem(anObject);
            }
        }

        @Override
        public Object getItem() {
            Object superRes = super.getItem();
            if (superRes instanceof String) {
                UserRepository rep = new UserRepository();
                UserInfo result = rep.getUserInfo((String) superRes);
                return result;
            }
            return superRes;
        }
    }
}

1 个答案:

答案 0 :(得分:2)

关注@ kleopatra的指示:我使用的是DefaultCellEditor而不是ComboBoxCellEditor。