获取JComboBox以在JTable中显示而不首先单击它

时间:2018-01-18 20:46:08

标签: java swing jtable jcombobox

我试图了解如何将JComboBox放入JTable中,因此我使用了JTable教程中的演示。

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.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;

/** 
 * TableRenderDemo is just like TableDemo, except that it
 * explicitly initializes column sizes and it uses a combo box
 * as an editor for the Sport column.
 */
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",
     "Snowboarding", new Integer(5), new Boolean(false)},
    {"John", "Doe",
     "Rowing", new Integer(3), new Boolean(true)},
    {"Sue", "Black",
     "Knitting", new Integer(2), new Boolean(false)},
    {"Jane", "White",
     "Speed reading", new Integer(20), new Boolean(true)},
    {"Joe", "Brown",
     "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();
        }
    });
}
}

通常情况下,JComboBox在点击之前不会显示。我想让它一直显示,以便用户知道该列中有一个组合框。我试过自定义渲染器(在这个论坛上找到了一些)来解决这个问题,但遇到的问题让我走上了一条错误的道路。是否有某个示例显示如何在不先单击的情况下显示组合框。 TIA。

2 个答案:

答案 0 :(得分:1)

渲染器看起来像:

class ComboBoxRenderer extends JComboBox implements TableCellRenderer
{
    public ComboBoxRenderer()
    {
        setBorder(null);
    }

    public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    {
        removeAllItems();
        addItem( value );

        return this;
    }
}

答案 1 :(得分:0)

您可以使用以下代码在第一次单击时调用Combobox编辑器。

library(tidyr)
library(dplyr)
library(tibble)

long_data = data.frame(X1=c("A", "B", "C", "D"), X2=c("a", "b", "c", "d"))

long_data %>% 
  spread(X1, 1) %>%
  mutate_at(vars(-X2), funs(if_else(is.na(.), 0, 1))) %>%
  column_to_rownames("X2") %>%
  write.table(file="TestData.csv", quote=F, sep=";")
#   A;B;C;D
# a;1;0;0;0
# b:0;1;0;0
# c;0;0;1;0
# d;0;0;0;1

expand.grid(long_data) %>%
  left_join(long_data %>% mutate(val=1)) %>%
  replace_na(list(val=0)) %>%
  write.table(file="TestData2.csv", quote=F, sep=";")
# X1;X2;val
# A;a;1
# B;a;0
# C;a;0
# D;a;0
# A;b;0
# B;b;1
# C;b;0
# D;b;0
# A;c;0
# B;c;0
# C;c;1
# D;c;0
# A;d;0
# B;d;0
# C;d;0
# D;d;1