JTable 有一列为 JCombobox,其模型根据用户在 JCombobox 编辑器组件中键入的文本进行更新

问题描述 投票:0回答:1

我需要一个 JTable,其中有一列作为 JCombobox。 JCombobox 编辑器已更新,以允许过滤 JCombobox 的内容。我找到了一些用于过滤 JCombobox 的答案和代码,它对于组合框效果很好,但是一旦我将它作为单元格编辑器添加到 JTable 列中,它就不能很好地工作。

以下是代码


import java.awt.BorderLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Arrays;

import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;

public class FilterComboBox extends JComboBox<String> {
    private ArrayList<String> entries;

    public FilterComboBox(ArrayList<String> entries) {
        DefaultComboBoxModel<String> model = (DefaultComboBoxModel<String>) this.getModel();
        model.addAll(entries);
        model.insertElementAt("", 0);

        model.setSelectedItem(model.getElementAt(0));

        this.entries = entries;
        this.setEditable(true);
        final JTextField textfield = (JTextField) this.getEditor().getEditorComponent();
        textfield.addKeyListener(new KeyAdapter() {
            public void keyReleased(KeyEvent ke) {
                System.out.println("Filtering the elements with  " + textfield.getText());
                comboFilter(textfield.getText());
            }
        });
    }

    public void comboFilter(String enteredText) {
        if (!this.isPopupVisible()) {
            System.out.println("Showing the popup");
            this.showPopup();
        }
        System.out.println("Filtering the elements");

        ArrayList<String> filterArray = new ArrayList<>();
        for(String entry: this.entries){
            if(entry.toLowerCase().indexOf(enteredText.toLowerCase()) >= 0){
                filterArray.add(entry);
                System.out.println(entry);
            }
        }
        
        DefaultComboBoxModel<String> model = (DefaultComboBoxModel<String>) this.getModel();
        model.removeAllElements();
        model.addAll(filterArray);
        
        JTextField textfield = (JTextField) this.getEditor().getEditorComponent();
        textfield.setText(enteredText);
        System.out.println("Filtering the elements: "+ this.isPopupVisible());
    } 

    public static void main(String[] args) throws Exception {

        ArrayList<String> entries = new ArrayList<>();
        entries.add("Snowboarding");
        entries.add("Knitting");
        entries.add("Jane");
        entries.add("Pool");
        entries.add("None of the above");
        entries.add("Rowing");
        entries.add("Kathy");
        JFrame frame = new JFrame("Adventure in Nepal - Combo Filter Test");
        FilterComboBox acb = new FilterComboBox(entries);
        JTable table1 = new JTable();

        table1.setModel(new DefaultTableModel(new Object[][] { 
                                                            {"", ""}, {"", ""}},(Object[])new String[] { "Text", "Text"}) {
          
            Class<?>[] columnTypes = new Class[] { String.class, String.class };
            boolean[] columnEditable = new boolean[] { true, true};
            public Class<?> getColumnClass(int columnIndex) {
                return this.columnTypes[columnIndex];
            }
            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return this.columnEditable[columnIndex];
            }
        });


        table1.setAutoCreateRowSorter(true);

        TableColumnModel cm = table1.getColumnModel();
        cm.getColumn(0).setCellEditor(new DefaultCellEditor(new FilterComboBox(entries)));
        

        JPanel p = new JPanel(new BorderLayout());
        p.add(new JScrollPane(table1), BorderLayout.NORTH);
        p.add(acb, BorderLayout.SOUTH);
        frame.setContentPane(p);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.setLocationRelativeTo(null);
        frame.setSize(500, 500);

        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    }
}

在上面的代码中,

acb
FilterComboBox 运行良好,但
table1
运行不佳。

基于一些强力调试,我发现

model.removeAllElements();
model.addAll(filterArray);
导致了问题,因为如果我删除它们,打印语句会指示正确的执行顺序。但这当然违背了这段代码的目的。

有人可以帮我让它工作吗?我怀疑组合框和 jtable 的关键事件以及在模型的

removeAllElements
addAll
函数调用上触发的内部事件处理不当。

java swing jtable jcombobox
1个回答
0
投票

使用 JTable 时,JComboBox 过滤似乎存在问题。

您可以尝试以下更改:

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JTextField;

public class FilterComboBox extends JComboBox<String> {
    private ArrayList<String> entries;

    public FilterComboBox(ArrayList<String> entries) {
        super(new DefaultComboBoxModel<>(entries.toArray(new String[0])));
        this.entries = entries;
        this.setEditable(true);
        final JTextField textfield = (JTextField) this.getEditor().getEditorComponent();
        textfield.addKeyListener(new KeyAdapter() {
            public void keyReleased(KeyEvent ke) {
                comboFilter(textfield.getText());
            }
        });
    }

    public void comboFilter(String enteredText) {
        if (!this.isPopupVisible()) {
            this.showPopup();
        }

        ArrayList<String> filterArray = new ArrayList<>();
        for (String entry : entries) {
            if (entry.toLowerCase().contains(enteredText.toLowerCase())) {
                filterArray.add(entry);
            }
        }

        DefaultComboBoxModel<String> model = (DefaultComboBoxModel<String>) this.getModel();
        model.removeAllElements();
        for (String entry : filterArray) {
            model.addElement(entry);
        }

        JTextField textfield = (JTextField) this.getEditor().getEditorComponent();
        textfield.setText(enteredText);
    }
}

对于主要方法:

public static void main(String[] args) throws Exception {
        ArrayList<String> entries = new ArrayList<>();
        entries.add("Snowboarding");
        entries.add("Knitting");
        entries.add("Jane");
        entries.add("Pool");
        entries.add("None of the above");
        entries.add("Rowing");
        entries.add("Kathy");

        JFrame frame = new JFrame("Adventure in Nepal - Combo Filter Test");
        FilterComboBox acb = new FilterComboBox(entries);
        JTable table1 = new JTable();

        table1.setModel(new DefaultTableModel(new Object[][] { 
            {"", ""}, {"", ""}}, new String[] { "Text", "Text" }) {
            Class<?>[] columnTypes = new Class[] { String.class, String.class };
            boolean[] columnEditable = new boolean[] { true, true };

            public Class<?> getColumnClass(int columnIndex) {
                return columnTypes[columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return columnEditable[columnIndex];
            }
        });

        table1.setAutoCreateRowSorter(true);

        TableColumnModel cm = table1.getColumnModel();
        cm.getColumn(0).setCellEditor(new DefaultCellEditor(new FilterComboBox(entries)));

        JPanel p = new JPanel(new BorderLayout());
        p.add(new JScrollPane(table1), BorderLayout.CENTER);
        p.add(acb, BorderLayout.SOUTH);
        frame.setContentPane(p);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.setLocationRelativeTo(null);
        frame.setSize(500, 500);

        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.