1

我正在使用 GlazedLists 的 AutoCompleteSupport 来包装用作 JTable 的单元格编辑器的 JComboBox,当我在编辑器中键入不在模型中的值时,我遇到了获取 selectedItem 的问题。

在您在 ComboBox 中键入不在列表中的内容后,问题出现在 stopCellEditing 方法中。即使在编辑器中输入了某些内容,当从 stopCellEditing 调用 getItem() 时,也会返回 null。请从下面的代码中查看 65。

我想从编辑器中获取项目,以便能够将其添加到 ComboBox 模型中。

import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.TextFilterator;
import ca.odell.glazedlists.swing.AutoCompleteSupport;
import java.awt.Component;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.HashMap;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;

public class TestComboBoxGlazedLists {

    public static void main(String[] args) {

        TestComboBoxGlazedLists test = new TestComboBoxGlazedLists();
        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
        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
        TestComboBoxGlazedLists.UserRepository rep = new TestComboBoxGlazedLists.UserRepository();
        TestComboBoxGlazedLists.UserInfo[] comboElements = rep.getAllUsers();
        DefaultComboBoxModel model = new DefaultComboBoxModel(comboElements);
        JComboBox comboBox = new JComboBox(model);

        // GlazedLists
        DefaultCellEditor cellEditor = new DefaultCellEditor(comboBox) {
            private Object originalValue;

            @Override
            public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
                originalValue = value;
                return super.getTableCellEditorComponent(table, value, isSelected, row, column);
            }

            @Override
            public boolean stopCellEditing() {
                JComboBox comboBox = (JComboBox) getComponent();
                ComboBoxModel comboModel = comboBox.getModel();

                // this value is null when the selected item is not from the list
                Object editingValue = getCellEditorValue();

                //  Needed because your TableModel is empty
                if (editingValue == null) {
                    return super.stopCellEditing();
                }

                int selectedIndex = -1;
                int modelSize = comboModel.getSize();
                for (int i = 0; i < modelSize; i++) {
                    if (editingValue.equals(comboModel.getElementAt(i))) {
                        selectedIndex = i;
                    }
                }

                //  Selecting item from model
                if (!(selectedIndex == -1)) {
                    return super.stopCellEditing();
                }

                if (!(editingValue instanceof TestComboBoxGlazedLists.UserInfo)) {
                    //  Confirm addition of new value
                    int result = JOptionPane.showConfirmDialog(
                            comboBox.getParent(),
                            "Add (" + editingValue + ") to table?",
                            "Update Model",
                            JOptionPane.YES_NO_OPTION);
                    if (result == JOptionPane.YES_OPTION) {
                        TestComboBoxGlazedLists.UserInfo newUser = new TestComboBoxGlazedLists.UserInfo(editingValue.toString(), null);
                        comboBox.addItem(newUser);
                        comboBox.setSelectedItem(newUser);
                        return super.stopCellEditing();
                    }
                }
                return false;
            }
        };
        // needs to be invoked from Event Dispatch Thread
        SwingUtilities.invokeLater(new TestComboBoxGlazedLists.AutocompleteComboRunnable(table, comboBox));
        // end GlazedLists

        table.getColumn("A").setCellEditor(cellEditor);
        table.getColumn("A").setCellRenderer(new TestComboBoxGlazedLists.CustomTableCellRenderer());
        // pack and show frame
        frame.pack();
        frame.setVisible(true);
    }

    public class AutocompleteComboRunnable implements Runnable {

        private JTable mTable;
        private JComboBox mComboBox;

        public AutocompleteComboRunnable(JTable table, JComboBox comboBox) {
            mTable = table;
            mComboBox = comboBox;
        }

        @Override
        public void run() {
            TextFilterator textFilterator = GlazedLists.textFilterator("firstName");
//                ComboBoxCellEditor cellEditor = new ComboBoxCellEditor(comboBox);

            TestComboBoxGlazedLists.UserRepository rep = new TestComboBoxGlazedLists.UserRepository();
            AutoCompleteSupport support = AutoCompleteSupport.install(mComboBox,
                    GlazedLists.eventListOf(rep.getAllUsers()),
                    textFilterator,
                    new TestComboBoxGlazedLists.UserInfoFormat());
            support.setStrict(false);

        }
    }

    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"
                TestComboBoxGlazedLists.UserInfo user = (TestComboBoxGlazedLists.UserInfo) value;
                return super.getTableCellRendererComponent(table, user.getFirstName(), isSelected, hasFocus, row, column);
            } else {
                return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            }
        }
    }

    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 {

        TestComboBoxGlazedLists.UserInfo[] comboElements;
        HashMap<String, TestComboBoxGlazedLists.UserInfo> objectsMap;

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

        }

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

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

    private class UserInfoFormat extends Format {

        @Override
        public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
            if (obj != null) {
                toAppendTo.append(((TestComboBoxGlazedLists.UserInfo) obj).getFirstName());
            }
            return toAppendTo;
        }

        @Override
        public Object parseObject(String source, ParsePosition pos) {
            TestComboBoxGlazedLists.UserRepository rep = new TestComboBoxGlazedLists.UserRepository();
            return rep.getUserInfo(source.substring(pos.getIndex()));
        }
    }
}
4

0 回答 0