JTable和自定义JComboBox

时间:2015-03-20 12:38:11

标签: java swing combobox jtable

我想将自定义JComboBox实现为JTable的CellEditor。我采用了原始Java示例并通过实现体育课程

对其进行了修改

请运行源代码,单击JComboBox,您将注意到ComboBox打开时不再选择所选项目。 我想将renderered项目保留在组合框选择中。

原文:http://docs.oracle.com/javase/tutorial/uiswing/components/table.html#combobox

public class Sport {
    private Integer id;
    private String name;

    public Sport(String name){
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

     public String toString() {
        return this.name;
    }
}



public class TableRenderDemo extends JPanel {
    private boolean DEBUG = false;

public TableRenderDemo() {
    super(new GridLayout(1,0));

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

    //Create the scroll pane and add the table to it.
    JScrollPane scrollPane = new JScrollPane(table);

    //Set up column sizes.
    initColumnSizes(table);

    //Fiddle with the Sport column's cell editors/renderers.
    setUpSportColumn(table, table.getColumnModel().getColumn(2));

    //Add the scroll pane to this panel.
    add(scrollPane);
}

/*
 * This method picks good column sizes.
 * If all column heads are wider than the column's cells'
 * contents, then you can just use column.sizeWidthToFit().
 */
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.
    JComboBox comboBox = new JComboBox();
    comboBox.addItem("Snowboarding");
    comboBox.addItem("Rowing");
    comboBox.addItem("Knitting");
    comboBox.addItem("Speed reading");
    comboBox.addItem("Pool");
    comboBox.addItem("None of the above");
    sportColumn.setCellEditor(new DefaultCellEditor(comboBox));

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

class MyTableModel extends AbstractTableModel {
    private String[] columnNames = {"First Name",
                                    "Last Name",
                                    "Sport",
                                    "# of Years",
                                    "Vegetarian"};
    private Object[][] data = {
    {"Kathy", "Smith",new Sport("Snowboarding"),
            new Integer(5), new Boolean(false)},
    {"John", "Doe",
     new Sport("Rowing"), new Integer(3), new Boolean(true)},
    {"Sue", "Black",
     new Sport("Knitting"), new Integer(2), new Boolean(false)},
    {"Jane", "White",
     new Sport("Speed reading"), new Integer(20), new Boolean(true)},
    {"Joe", "Brown",
     new Sport("Pool"), new Integer(10), 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];
    }

    /*
     * JTable uses this method to determine the default renderer/
     * editor for each cell.  If we didn't implement this method,
     * then the last column would contain text ("true"/"false"),
     * rather than a check box.
     */
    public Class getColumnClass(int c) {
        return getValueAt(0, c).getClass();
    }

    /*
     * Don't need to implement this method unless your table's
     * editable.
     */
    public boolean isCellEditable(int row, int col) {
        //Note that the data/cell address is constant,
        //no matter where the cell appears onscreen.
        if (col < 2) {
            return false;
        } else {
            return true;
        }
    }

    /*
     * Don't need to implement this method unless your table's
     * data can change.
     */
    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("--------------------------");
    }
}

/**
 * Create the GUI and show it.  For thread safety,
 * this method should be invoked from the
 * event-dispatching thread.
 */
private static void createAndShowGUI() {
    //Create and set up the window.
    JFrame frame = new JFrame("TableRenderDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //Create and set up the content pane.
    TableRenderDemo newContentPane = new TableRenderDemo();
    newContentPane.setOpaque(true); //content panes must be opaque
    frame.setContentPane(newContentPane);

    //Display the window.
    frame.pack();
    frame.setVisible(true);
}

public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application's GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
}
}

好的我包括以下内容,但仍然存在同样的问题:

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

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

2 个答案:

答案 0 :(得分:2)

您的模型包含Sport类的实例,但JCombobox包含字符串。这就是设置选择无法找到适当值的原因。

尝试添加这样的运动

 comboBox.addItem(new Sport("Rowing"));

并且重写Sport类的toString()方法以返回名称(更简单的方法)。或者将自定义渲染器添加到运动组合框中。

答案 1 :(得分:2)

您还需要覆盖Sport类的equals(...)hashcode(...)方法。 Java Collection方法依赖于这些方法来确定对象实例在进行搜索时的相等性。

@Override
public boolean equals(Object object)
{
    Sport sport = (Sport)object;
    return this.name.equals( sport.getName() );
}

@Override
public int hashCode()
{
    return name.hashCode();
}

另外,请阅读Object API以获取有关这些方法的更多信息。