【问题标题】:JTable with different JCombobox for each line每行具有不同 JCombobox 的 JTable
【发布时间】:2017-05-24 15:36:10
【问题描述】:

我有一个在运行时加载行的表。加载后,用户需要从每行第一列的JComboBox 中选择一个项目。然后他需要在每一行的同一行中从另一个JComboBox 中选择一个项目。第二个JComboBox的内容取决于第一个JComboBox的选择。

我现在编码的方式是更改整个第二列的组合框内容。

columnProfile.setCellEditor(new DefaultCellEditor(comboBoxProf))

有没有办法让每一行都有一个不同的组合框对象,以便我每次在第一个组合框中选择一个值时都可以处理它?

在用户点击提交之前,行数是不固定的。他可以添加和删除行。

我使用了 Oracle 的基本表格示例,并进行了更改以反映我目前正在做的事情

import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;


import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;


public class TableRenderDemo extends JPanel {
    private boolean DEBUG = false;
    JComboBox comboBox2;
    JComboBox comboBox1;
    public TableRenderDemo() {
        super(new GridLayout(1,0));

        JTable table = new JTable(new MyTableModel());
        table.setPreferredScrollableViewportSize(new Dimension(500, 70));
        table.setFillsViewportHeight(true);
        JScrollPane scrollPane = new JScrollPane(table);
        initColumnSizes(table);

        setUpSportColumn(table, table.getColumnModel().getColumn(2));
        setUpYearsColumn(table, table.getColumnModel().getColumn(3));

        add(scrollPane);
        table.getModel().addTableModelListener(new TableModelListener() {

            public void tableChanged(TableModelEvent e) {

                if (e.getColumn() == 2){
                    comboBox2.removeAllItems();
                    /*REFILL COMBOBOX WITH WHAT I NEED FOR THIS ROW ONLY*/
                }


            }
                  }); 
    }

    private void initColumnSizes(JTable table) {
        MyTableModel model = (MyTableModel)table.getModel();
        TableColumn column = null;
        Component comp = null;
        int headerWidth = 0;
        int cellWidth = 0;
        Object[] longValues = model.longValues;
        TableCellRenderer headerRenderer =
            table.getTableHeader().getDefaultRenderer();

        for (int i = 0; i < 5; i++) {
            column = table.getColumnModel().getColumn(i);

            comp = headerRenderer.getTableCellRendererComponent(
                                 null, column.getHeaderValue(),
                                 false, false, 0, 0);
            headerWidth = comp.getPreferredSize().width;

            comp = table.getDefaultRenderer(model.getColumnClass(i)).
                             getTableCellRendererComponent(
                                 table, longValues[i],
                                 false, false, 0, i);
            cellWidth = comp.getPreferredSize().width;

            if (DEBUG) {
                System.out.println("Initializing width of column "
                                   + i + ". "
                                   + "headerWidth = " + headerWidth
                                   + "; cellWidth = " + cellWidth);
            }

            column.setPreferredWidth(Math.max(headerWidth, cellWidth));
        }
    }

    public void setUpSportColumn(JTable table,
                                 TableColumn sportColumn) {
        //Set up the editor for the sport cells.
        comboBox1 = new JComboBox();
        comboBox1.addItem("Snowboarding");
        comboBox1.addItem("Rowing");
        comboBox1.addItem("Knitting");
        comboBox1.addItem("Speed reading");
        comboBox1.addItem("Pool");
        comboBox1.addItem("None of the above");
        sportColumn.setCellEditor(new DefaultCellEditor(comboBox1));


        DefaultTableCellRenderer renderer =
                new DefaultTableCellRenderer();
        renderer.setToolTipText("Click for combo box");
        sportColumn.setCellRenderer(renderer);
    }
    public void setUpYearsColumn(JTable table,
            TableColumn yearColumn) {

comboBox2 = new JComboBox();
comboBox2.addItem("1");
comboBox2.addItem("2");
comboBox2.addItem("3");
comboBox2.addItem("4");
comboBox2.addItem("5");
comboBox2.addItem("6");
yearColumn.setCellEditor(new DefaultCellEditor(comboBox2));

//Set up tool tips for the sport cells.
DefaultTableCellRenderer renderer =
new DefaultTableCellRenderer();
renderer.setToolTipText("Click for combo box");
yearColumn.setCellRenderer(renderer);
}

    class MyTableModel extends AbstractTableModel {
        private String[] columnNames = {"First Name",
                                        "Last Name",
                                        "Sport",
                                        "# of Years",
                                        "Vegetarian"};
        private Object[][] data = {
        {"Kathy", "Smith",
         "Snowboarding", "1", new Boolean(false)},
        {"John", "Doe",
         "Rowing", "1", new Boolean(true)},
        {"Sue", "Black",
         "Knitting", "1", new Boolean(false)},
        {"Jane", "White",
         "Speed reading", "1", new Boolean(true)},
        {"Joe", "Brown",
         "Pool", "1", new Boolean(false)}
        };

        public final Object[] longValues = {"Jane", "Kathy",
                                            "None of the above",
                                            new Integer(20), Boolean.TRUE};

        public int getColumnCount() {
            return columnNames.length;
        }

        public int getRowCount() {
            return data.length;
        }

        public String getColumnName(int col) {
            return columnNames[col];
        }

        public Object getValueAt(int row, int col) {
            return data[row][col];
        }


        public Class getColumnClass(int c) {
            return getValueAt(0, c).getClass();
        }


        public boolean isCellEditable(int row, int col) {

            if (col < 2) {
                return false;
            } else {
                return true;
            }
        }


        public void setValueAt(Object value, int row, int col) {
            if (DEBUG) {
                System.out.println("Setting value at " + row + "," + col
                                   + " to " + value
                                   + " (an instance of "
                                   + value.getClass() + ")");
            }

            data[row][col] = value;
            fireTableCellUpdated(row, col);

            if (DEBUG) {
                System.out.println("New value of data:");
                printDebugData();
            }
        }

        private void printDebugData() {
            int numRows = getRowCount();
            int numCols = getColumnCount();

            for (int i=0; i < numRows; i++) {
                System.out.print("    row " + i + ":");
                for (int j=0; j < numCols; j++) {
                    System.out.print("  " + data[i][j]);
                }
                System.out.println();
            }
            System.out.println("--------------------------");
        }
    }


    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("TableRenderDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


        TableRenderDemo newContentPane = new TableRenderDemo();
        newContentPane.setOpaque(true); 
        frame.setContentPane(newContentPane);

        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {

        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

【问题讨论】:

  • 请在minimal reproducible examplesscce 上发布您的最佳尝试,在那里您将代码压缩成最小的位,小到足以将您的问题作为代码格式的文本发布,仍然可以编译和运行,没有外部依赖项(例如需要链接到数据库或图像),没有与您的问题无关的额外代码,但仍然可以演示您的问题。这将使人们更容易回答您的问题并帮助您解决问题。
  • 一种解决方案是让您的单元格编辑器扩展 DefaultCellEditor,覆盖getTableCellEditorComponent(...),并更改此编辑器拥有的JComboBox 的模型。欲了解更多详情,请再次向我们展示您的minimal reproducible example
  • 我已经添加了代码。谢谢!
  • 请您的自己的代码,显示您尝试使用这两个组合框的代码。
  • 那里可以看到,我有combobox1和combobox2。您可以运行此代码。我只是不愿意分享我的整个代码,因为我的工作不喜欢它。但是那里的东西代表了我想做的事情。查看行 /*REFILL COMBOBOX WITH WHAT I NEED FOR this ROW */

标签: java swing jtable jcombobox


【解决方案1】:

假设您将数据保存在 Map&lt;String, List&lt;String&gt;&gt; 中,其中 Map 的键表示第一个 JComboBox 保存的值,而 Map 的值表示第二列的 JComboBox 保存的更改值(不需要设置数据这样,但对于 MCVE/演示目的来说很容易),并将此地图称为 dataMap,那么您的列编辑器可能看起来像:

    column1.setCellEditor(new DefaultCellEditor(combo1) {
        @SuppressWarnings("unchecked")
        @Override
        public Component getTableCellEditorComponent(JTable table, Object value,
                boolean isSelected, int row, int column) {

            // the items that will fill our JComboBox. Initially its empty
            Object[] items = new Object[]{};

            // get the value in the column to the left
            Object column0Value = table.getValueAt(row, column - 1);
            if (column0Value != null) {
                // if the value is not null, then get the map's values
                // and use it to fill our items array
                items = dataMap.get(column0Value).toArray();
            } 

            // get the super component, the JComboBox that is being used
            // as an editor:
            JComboBox<Object> superCombo = (JComboBox<Object>) super.getTableCellEditorComponent(table, value, isSelected,
                    row, column);

            // create a model and fill with items
            DefaultComboBoxModel<Object> comboModel = new DefaultComboBoxModel<>(items);

            // set the cell editor's model and return
            superCombo.setModel(comboModel);
            return superCombo;
        }
    });

例如,请检查此 MCVE 作为使用上述单元格编辑器的示例,并作为一个 MCVE 示例,该示例将在您未来的问题中运行良好

import java.awt.Component;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;

@SuppressWarnings("serial")
public class TableWithMultCombos extends JPanel {
    private static final String[] COLUMN_NAMES = { "Day of Week", "Number" };
    private Map<String, List<String>> dataMap = new LinkedHashMap<>();
    private DefaultTableModel tblModel = new DefaultTableModel(COLUMN_NAMES, 5);
    private JTable table = new JTable(tblModel);
    private DefaultComboBoxModel<Object> combo2Model = new DefaultComboBoxModel<>();
    private JComboBox<Object> combo0 = null;
    private JComboBox<Object> combo1 = new JComboBox<>(combo2Model);

    public TableWithMultCombos() {
        dataMap.put("Monday", Arrays.asList(new String[] { "Mon - 1", "Mon - 2", "Mon - 3", "Mon - 4" }));
        dataMap.put("Tuesday", Arrays.asList(new String[] { "Tues - 1", "Tues - 2", "Tues - 3", "Tues - 4" }));
        dataMap.put("Wednesday", Arrays.asList(new String[] { "Wed - 1", "Wed - 2", "Wed - 3", "Wed - 4" }));
        dataMap.put("Thursday", Arrays.asList(new String[] { "Thurs - 1", "Thurs - 2", "Thurs - 3", "Thurs - 4" }));
        dataMap.put("Friday", Arrays.asList(new String[] { "Fri - 1", "Fri - 2", "Fri - 3", "Fri - 4" }));
        combo0 = new JComboBox<>(dataMap.keySet().toArray());

        TableColumn column0 = table.getColumnModel().getColumn(0);
        column0.setCellEditor(new DefaultCellEditor(combo0));

        TableColumn column1 = table.getColumnModel().getColumn(1);
        column1.setCellEditor(new DefaultCellEditor(combo1) {
            @SuppressWarnings("unchecked")
            @Override
            public Component getTableCellEditorComponent(JTable table, Object value,
                    boolean isSelected, int row, int column) {

                // the items that will fill our JComboBox. Initially its empty
                Object[] items = new Object[]{};

                // get the value in the column to the left
                Object column0Value = table.getValueAt(row, column - 1);
                if (column0Value != null) {
                    // if the value is not null, then get the map's values
                    // and use it to fill our items array
                    items = dataMap.get(column0Value).toArray();
                } 

                // get the super component, the JComboBox that is being used
                // as an editor:
                JComboBox<Object> superCombo = (JComboBox<Object>) super.getTableCellEditorComponent(table, value, isSelected,
                        row, column);

                // create a model and fill with items
                DefaultComboBoxModel<Object> comboModel = new DefaultComboBoxModel<>(items);

                // set the cell editor's model and return
                superCombo.setModel(comboModel);
                return superCombo;
            }
        });

        table.setFillsViewportHeight(true);
        add(new JScrollPane(table));
    }

    private static void createAndShowGui() {
        TableWithMultCombos mainPanel = new TableWithMultCombos();

        JFrame frame = new JFrame("TableWithMultCombos");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

【讨论】:

  • 非常感谢,我能够运行这段代码,现在明白我需要做什么了。真的很感激
猜你喜欢
  • 1970-01-01
  • 2011-05-08
  • 2011-10-12
  • 2015-10-16
  • 1970-01-01
  • 2015-01-07
  • 1970-01-01
  • 1970-01-01
  • 2012-09-26
相关资源
最近更新 更多