首页 > 解决方案 > 无法使用 TableModel 在 JTable 中显示 JComboBox

问题描述

下面的代码显示 aJTable有 3 列,分别包含 a JComboBox、 aString和 a double,并且应该显示黄色。问题是我无法JComboBox在第一列中显示为...一个组合框;相反,我得到一个String说法“ javax.swing.JComboBox...”。我究竟做错了什么?

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableModel;
import java.awt.*;

public class BadDialog extends JDialog {
    //Instantiate the data for the table, which is 2 rows x 3 cols
    private final JComboBox col0ComboBox = new JComboBox(new String[]{"aaa", "bbb"}); //Goes in all rows of Col 0
    private final String[] col1Data = {"Mickey", "Mouse"};
    private final double[] col2Data = {111, 222};

    public BadDialog() {
        //Instantiate table
        JTable badTable = new JTable();

        //Assign a tableModel to the table, put the table in a scroller, add it to this dialog, and sort out the renderer
        TableModel badTableModel = new BadTableModel();
        badTable.setModel(badTableModel);
        JScrollPane scroller = new JScrollPane(badTable);
        add(scroller);
        BadTableCellRenderer badTableCellRenderer = new BadTableCellRenderer();
        badTable.setDefaultRenderer(JComboBox.class, badTableCellRenderer); //Col 0
        badTable.setDefaultRenderer(String.class, badTableCellRenderer); //Col 1
        badTable.setDefaultRenderer(Double.class, badTableCellRenderer); //Col 2

        //Assign col0ComboBox to Col 0
        badTable.getColumnModel().getColumn(0).setCellEditor(new DefaultCellEditor(col0ComboBox));

        //Show the dialog
        setPreferredSize(new Dimension(300, 470));
        pack();
        setModal(true);
        setLocation(10, 10);
        setVisible(true);
    }

    private final class BadTableModel extends AbstractTableModel {
        @Override
        public int getRowCount() {
            return 2;
        }

        @Override
        public int getColumnCount() {
            return 3;
        }

        @Override
        public Object getValueAt(int rowIndex, int colIndex) {
            if (colIndex == 0) return col0ComboBox;
            if (colIndex == 1) return col1Data[rowIndex];
            return col2Data[rowIndex];
        }

        @Override
        public Class<?> getColumnClass(int colIndex) {
            if (colIndex == 0) return JComboBox.class;
            if (colIndex == 1) return String.class;
            return Double.class;
        }
    }

    private static class BadTableCellRenderer extends DefaultTableCellRenderer {

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
            Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);

            //Make all columns yellow
            c.setBackground(Color.YELLOW);
            c.setForeground(Color.RED);
            c.setFont(new Font("Dialog", Font.PLAIN, 12));
            return c;
        }
    }

    public static void main(String[] args) {
        new BadDialog();
    }
}

标签: javaswingjtable

解决方案


永远不要在 TableModel 中返​​回组件。拥有单独的模型和视图的全部意义在于模型只包含数据,而不包含组件。模型的工作是提供数据;视图的工作是确定如何显示该数据。

您的 TableModel 的 getColumnClass 方法应如下所示:

public Class<?> getColumnClass(int colIndex) {
    if (colIndex == 0) return String.class; // String, not JComboBox
    if (colIndex == 1) return String.class;
    return Double.class;
}

并且您的 getValueAt 方法需要返回该行的实际数据值

public Object getValueAt(int rowIndex, int colIndex) {
    if (colIndex == 0) return (rowIndex % 1 == 0 ? "aaa" : "bbb");
    if (colIndex == 1) return col1Data[rowIndex];
    return col2Data[rowIndex];
}

单元格渲染器是视图的一部分,而不是模型,因此它可以使用 JComboBox。您的渲染需要使用value参数来修改您的 JComboBox:

private static class BadTableCellRenderer extends DefaultTableCellRenderer {

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
        if (row != 0) {
            return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
        }

        JComboBox c = col0ComboBox;
        c.setSelectedItem(value);

        //Make all columns yellow
        c.setBackground(Color.YELLOW);
        c.setForeground(Color.RED);
        c.setFont(new Font("Dialog", Font.PLAIN, 12));

        return c;
    }
}

推荐阅读