Java Swing Multi Column Autocomplete Combobox

Ich benötige eine effiziente Produktartikelsuch-GUI für die Point-of-Sale-Anwendung. Derzeit verwende ich ein Popup-Fenster im Textfeld und füge es der Tabelle hinzu, aber es ist nicht effizient.

In meinem Popup-Fenster wird nur der Produktcode angezeigt. Ich muss andere Produktdetails wie CODE, Kategorie, Name, Preis usw. anzeigen, um das richtige Produkt zu ermitteln. ! [Bildbeschreibung hier eingeben] [1]

Folgende Bilder sind meine Voraussetzung.

//////////////////////////////// Ich habe die Antwort "Edit mr.splungebob", um die AutoCompleate-Combobox zu erstellen, aber es gibt ein Problem mit der Listenfilterung Bitte überprüfen Sie den Code und helfen Sie mir, ihn zu entwickeln.

Im Folgenden ist der Code aufgeführt, den ich zur Antwort // DetailedComboBox hinzugefügt habe

    /*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package test;

    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Point;
    import java.awt.event.*;
    import java.util.*;
    import javax.swing.*;
    import javax.swing.event.ListSelectionEvent;
    import javax.swing.event.ListSelectionListener;
    import javax.swing.plaf.basic.BasicComboPopup;

import javax.swing.plaf.basic.ComboPopup;
import javax.swing.plaf.metal.MetalComboBoxUI;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

/**
 *
 * @author W.A.R.R.Wijesinghe
 */
public class DetailedComboBox extends JComboBox {

    public static enum Alignment {

        LEFT, RIGHT
    }
    private List<List<? extends Object>> tableData;
    private String[] columnNames;
    private int[] columnWidths;
    private int displayColumn;
    private Alignment popupAlignment = Alignment.LEFT;

    /**
     * Construct a TableComboBox object
     */
    public DetailedComboBox(String[] colNames, int[] colWidths, int displayColumnIndex) {
        super();
        this.columnNames = colNames;
        this.columnWidths = colWidths;
        this.displayColumn = displayColumnIndex;

        setUI(new TableComboBoxUI());
        setEditable(true);
        this.setSelectedIndex(-1);
        JTextField field = (JTextField) this.getEditor().getEditorComponent();
        field.setText("");
        field.addKeyListener(new ComboKeyHandler(this));
    }

    /**
     * Set the type of alignment for the popup table
     */
    public void setPopupAlignment(Alignment alignment) {
        popupAlignment = alignment;
    }

    /**
     * Populate the combobox and drop-down table with the supplied data. If the
     * supplied List is non-null and non-empty, it is assumed that the data is a
     * List of Lists to be used for the drop-down table. The combobox is also
     * populated with the column data from the column defined by
     * <code>displayColumn</code>.
     */
    public void setTableData(List<List<? extends Object>> tableData) {
        this.tableData = (tableData == null
                ? new ArrayList<List<? extends Object>>() : tableData);

        // even though the incoming data is for the table, we must also
        // populate the combobox's data, so first clear the previous list.
        removeAllItems();

        // then load the combobox with data from the appropriate column
        Iterator<List<? extends Object>> iter = this.tableData.iterator();
        while (iter.hasNext()) {
            List<? extends Object> rowData = iter.next();
            addItem(rowData.get(displayColumn));
        }
    }

    public List<? extends Object> getSelectedRow() {
        return tableData.get(getSelectedIndex());
    }

    public List<? extends Object> getRowAt(int row) {
        return tableData.get(row);
    }

    /**
     * The handler for the combobox's components
     */
    private class TableComboBoxUI extends MetalComboBoxUI {

        /**
         * Create a popup component for the ComboBox
         */
        @Override
        protected ComboPopup createPopup() {
            return new TableComboPopup(comboBox, this);
        }

        /**
         * Return the JList component
         */
        public JList getList() {
            return listBox;
        }
    }

    /**
     * The drop-down of the combobox, which is a JTable instead of a JList.
     */
    private class TableComboPopup extends BasicComboPopup implements ListSelectionListener, ItemListener {

        private final JTable table;
        private TableComboBoxUI comboBoxUI;
        private PopupTableModel tableModel;
        private JScrollPane scroll;
//    private JList list = new JList();
//    private ListSelectionListener selectionListener;
//    private ItemListener itemListener;

        /**
         * Construct a popup component that's a table
         */
        public TableComboPopup(JComboBox combo, TableComboBoxUI ui) {
            super(combo);
            this.comboBoxUI = ui;

            tableModel = new PopupTableModel();
            table = new JTable(tableModel);
            table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
            table.getTableHeader().setReorderingAllowed(false);

            TableColumnModel tableColumnModel = table.getColumnModel();
            tableColumnModel.setColumnSelectionAllowed(false);

            for (int index = 0; index < table.getColumnCount(); index++) {
                TableColumn tableColumn = tableColumnModel.getColumn(index);
                tableColumn.setPreferredWidth(columnWidths[index]);
            }

            scroll = new JScrollPane(table);
            scroll.setHorizontalScrollBarPolicy(
                    JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
            scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

            ListSelectionModel selectionModel = table.getSelectionModel();
            selectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            selectionModel.addListSelectionListener(this);
            combo.addItemListener(this);

            table.addMouseListener(new MouseAdapter() {

                @Override
                public void mousePressed(MouseEvent event) {
                    Point p = event.getPoint();
                    int row = table.rowAtPoint(p);

                    comboBox.setSelectedIndex(row);
                    hide();
                }
            });

            table.setBackground(UIManager.getColor("ComboBox.listBackground"));
            table.setForeground(UIManager.getColor("ComboBox.listForeground"));
        }

        /**
         * This method is overridden from BasicComboPopup
         */
        @Override
        public void show() {
            if (isEnabled()) {
                super.removeAll();

                int scrollWidth = table.getPreferredSize().width
                        + ((Integer) UIManager.get("ScrollBar.width")).intValue() + 1;
                int scrollHeight = comboBoxUI.getList().
                        getPreferredScrollableViewportSize().height;
                scroll.setPreferredSize(new Dimension(scrollWidth, scrollHeight));

                super.add(scroll);

                ListSelectionModel selectionModel = table.getSelectionModel();
                selectionModel.removeListSelectionListener(this);
                selectRow();
                selectionModel.addListSelectionListener(this);

                int scrollX = 0;
                int scrollY = comboBox.getBounds().height;

                if (popupAlignment == Alignment.RIGHT) {
                    scrollX = comboBox.getBounds().width - scrollWidth;
                }

                show(comboBox, scrollX, scrollY);
            }
        }

        /**
         * Implemention of ListSelectionListener
         */
        @Override
        public void valueChanged(ListSelectionEvent event) {
            comboBox.setSelectedIndex(table.getSelectedRow());
        }

        /**
         * Implemention of ItemListener
         */
        @Override
        public void itemStateChanged(ItemEvent event) {
            if (event.getStateChange() != ItemEvent.DESELECTED) {
                ListSelectionModel selectionModel = table.getSelectionModel();
                selectionModel.removeListSelectionListener(this);
                selectRow();
                selectionModel.addListSelectionListener(this);
            }
        }

        /**
         * Sync the selected row of the table with the selected row of the
         * combo.
         */
        private void selectRow() {
            int index = comboBox.getSelectedIndex();

            if (index != -1) {
                table.setRowSelectionInterval(index, index);
                table.scrollRectToVisible(table.getCellRect(index, 0, true));
            }
        }
    }

    /**
     * A model for the popup table's data
     */
    private class PopupTableModel extends AbstractTableModel {

        /**
         * Return the # of columns in the drop-down table
         */
        @Override
        public int getColumnCount() {
            return columnNames.length;
        }

        /**
         * Return the # of rows in the drop-down table
         */
        @Override
        public int getRowCount() {
            return tableData == null ? 0 : tableData.size();
        }

        /**
         * Determine the value for a given cell
         */
        @Override
        public Object getValueAt(int row, int col) {
            if (tableData == null || tableData.size() == 0) {
                return "";
            }

            return tableData.get(row).get(col);
        }

        /**
         * All cells in the drop-down table are uneditable
         */
        @Override
        public boolean isCellEditable(int row, int col) {
            return false;
        }

        /**
         * Pull the column names out of the tableInfo object for the header
         */
        @Override
        public String getColumnName(int column) {
            String columnName = null;

            if (column >= 0 && column < columnNames.length) {
                columnName = columnNames[column].toString();
            }

            return (columnName == null) ? super.getColumnName(column) : columnName;
        }
    }
}

class ComboKeyHandler extends KeyAdapter {

    private final DetailedComboBox comboBox;
    //  private final Vector<String> list = new Vector<String>();
    private final List<List<?>> list = new ArrayList<>();

    public ComboKeyHandler(DetailedComboBox combo) {
        this.comboBox = combo;
        for (int i = 0; i < comboBox.getModel().getSize(); i++) {


            List<? extends Object> rowData = combo.getRowAt(i);
            // name.setText(rowData.get(1).toString());
            //  capital.setText(rowData.get(2).toString());
            list.add(rowData);
            // list.addElement((String) comboBox.getItemAt(i));
        }
    }
    private boolean shouldHide = false;

    @Override
    public void keyTyped(final KeyEvent e) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                String text = ((JTextField) e.getSource()).getText();
                System.out.println(text);
                if (text.length() == 0) {
                    setSuggestionModel(comboBox, list, "");
                    comboBox.hidePopup();
                } else {
                    List<List<?>> m = getSuggestedModel(list, text);
                    if (m.isEmpty() || shouldHide) {
                        comboBox.hidePopup();
                    } else {
                        setSuggestionModel(comboBox, m, text);
                        comboBox.showPopup();
                    }
                }
            }
        });
    }

    @Override
    public void keyPressed(KeyEvent e) {
        JTextField textField = (JTextField) e.getSource();
        String text = textField.getText();
        shouldHide = false;
        switch (e.getKeyCode()) {
            case KeyEvent.VK_RIGHT:


                for (Iterator<List<?>> it = list.iterator(); it.hasNext();) {
                    if (!it.next().contains("How")) {
                        it.remove(); // NOTE: Iterator's remove method, not ArrayList's, is used.
                    }
                    return;
                }

                /*
                 * for (String s : list { if (s.startsWith(text)) {
                 * textField.setText(s); return; } }
                 *
                 */

                break;
            case KeyEvent.VK_ENTER:
                if (!list.contains(text)) {
                    list.add(new ArrayList<>(Arrays.asList(text, "a", "a")));

                    //setSuggestionModel(comboBox, new DefaultComboBoxModel(list), text);
                    setSuggestionModel(comboBox, getSuggestedModel(list, text), text);
                }
                shouldHide = false;
                break;
            case KeyEvent.VK_ESCAPE:
                shouldHide = true;
                break;
            default:
                break;
        }
    }

    private static void setSuggestionModel(DetailedComboBox comboBox, List<List<?>> newList, String str) {
        comboBox.setTableData(newList);
        comboBox.setSelectedIndex(-1);
        ((JTextField) comboBox.getEditor().getEditorComponent()).setText(str);
    }

    private static List<List<?>> getSuggestedModel(List<List<?>> list, String text) {
        List<List<?>> m = new ArrayList<>();


        for (Iterator<List<?>> it = list.iterator(); it.hasNext();) {
            if (!it.next().contains(text)) {
                it.remove(); // NOTE: Iterator's remove method, not ArrayList's, is used.
            }
            m = (List<List<?>>) it;
        }
        return m;

        /*
         * for (String s : list) { if (s.startsWith(text)) { m.addElement(s); }
         * } return m;
         *
         */
    }
}

// DetailedComboBoxDemo

    /*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package test;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.*;

/**
 *
 * @author W.A.R.R.Wijesinghe
 */
public class DetailedComboBoxDemo implements Runnable {

    private DetailedComboBox combo;
    private JTextField name;
    private JTextField capital;

    @Override
    public void run() {
        List<List<?>> tableData = new ArrayList<>();
        tableData.add(new ArrayList<>(  Arrays.asList("MD", "Maryland", "Annapolis")));

        tableData.add(new ArrayList<>(
                Arrays.asList("NH", "New Hampshire", "Concord")));
        tableData.add(new ArrayList<>(
                Arrays.asList("NJ", "New Jersey", "Trenton")));
        tableData.add(new ArrayList<>(
                Arrays.asList("NM", "New Mexico", "Santa Fe")));
        tableData.add(new ArrayList<>(
                Arrays.asList("ND", "North Dakota", "Bismark")));

        String[] columns = new String[]{"State", "Name", "Capital"};
        int[] widths = new int[]{50, 100, 100};

        combo = new DetailedComboBox(columns, widths, 0);
        combo.setTableData(tableData);
        combo.setSelectedIndex(-1);
        combo.setPopupAlignment(DetailedComboBox.Alignment.LEFT);
                combo.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                showDetails();
            }
        });

        name = new JTextField(10);
        capital = new JTextField(10);
        name.setEditable(false);
        capital.setEditable(false);

        JPanel p = new JPanel(new FlowLayout());
        p.add(new JLabel("State"));
        p.add(combo);
        p.add(new JLabel("Name"));
        p.add(name);
        p.add(new JLabel("Capital"));
        p.add(capital);

        JFrame frame = new JFrame("DetailedComboBox Demo");

        frame.getContentPane().add(p, BorderLayout.CENTER);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private void showDetails() {
        List<? extends Object> rowData = combo.getSelectedRow();
        name.setText(rowData.get(1).toString());
        capital.setText(rowData.get(2).toString());
    }

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

Antworten auf die Frage(2)

Ihre Antwort auf die Frage