简体   繁体   中英

How to implement correctly an JComboBox in a JTable?

What I only want is to implement correctly the sixth column of my Jtable with an JComboBox. When I click on the field the combobox suddenly appears, but without clicking I have the JComponent reference as String. I defined an own tableModel and tableCellrenderer.

here is my Code:

package examples;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.util.EventObject;

import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.CellEditorListener;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;

public class MyTableExample2 {
    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {

                try {
                    UIManager.setLookAndFeel(UIManager
                            .getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException
                        | IllegalAccessException
                        | UnsupportedLookAndFeelException e) {
                    e.printStackTrace();
                }

                @SuppressWarnings("unused")
                JFrame frame = new MyFrame();
            }
        });

    }
}

class MyFrame extends JFrame {

    private static final long serialVersionUID = 1L;
    private JComboBox<String> comboBox = new JComboBox<String>(new String[] {
            "Me", "You", "They" });
    private String[] columnNames = { "First Name", "Last Name", "Sport",
            "# of Years", "Vegetarian", "ComboBox" };
    private Object[][] data = {
            { "Kathy", "Smith", "Snowboarding", new Integer(5),
                    new Boolean(true), comboBox },
            { "John", "Doe", "Rowing", new Integer(3), new Boolean(true),
                    comboBox },
            { "Sue", "Black", "Knitting", new Integer(2), new Boolean(false),
                    comboBox },
            { "Jane", "White", "Speed reading", new Integer(20),
                    new Boolean(true), comboBox },
            { "Joe", "Brown", "Pool", new Integer(10), new Boolean(false),
                    comboBox } };

    private JTable jTable = new JTable(new MyTableModel());
    private JScrollPane scrollPane = new JScrollPane(jTable);
    private Font font = getContentPane().getFont().deriveFont(Font.BOLD, 15);

    private class MyTableCellRenderer extends JLabel implements
            TableCellRenderer {

        private static final long serialVersionUID = 1L;

        public MyTableCellRenderer() {
            setOpaque(true);
            setLayout(new BorderLayout());
        }

        @Override
        public Component getTableCellRendererComponent(JTable table,
                Object value, boolean isSelected, boolean hasFocus, int row,
                int column) {
            Font font = getFont().deriveFont(Font.BOLD, 15);
            table.setRowHeight((int) getPreferredSize().getHeight() + 5);

            if ((row % 2) == 0) {
                setBackground(new Color(224, 255, 255));
            } else {
                setBackground(new Color(135, 206, 250));
            }

            if (isSelected) {
                setBackground(new Color(0, 0, 255));
            }

            setForeground(Color.BLACK);
            setText(value.toString());
            setFont(font);

            return this;
        }

    }

    private TableCellRenderer tableCellRend = new MyTableCellRenderer();

    public MyFrame() {
        super("JTable");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        jTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);

        jTable.setColumnSelectionAllowed(false);
        jTable.setRowSelectionAllowed(true);
        jTable.setFillsViewportHeight(true);
        jTable.setFont(font);
        jTable.setRowHeight(20);
        jTable.setGridColor(new Color(100, 149, 237));
        jTable.getColumnModel().getColumn(5)
                .setCellEditor(new DefaultCellEditor(comboBox));
         jTable.setDefaultRenderer(Object.class, tableCellRend);
         jTable.setAutoCreateRowSorter(true); 

        getContentPane().add(scrollPane);

        pack();
        centerWindow();
        setVisible(true);

    }

    private class MyTableModel implements TableModel {

        @Override
        public void addTableModelListener(TableModelListener l) {
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {

            switch (columnIndex) {
            case 0:
                return String.class;
            case 1:
                return String.class;
            case 2:
                return String.class;
            case 3:
                return Object.class;
            case 4:
                return Object.class;
            case 5:
                return String.class;
            default:
                return null;
            }

        }

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

        @Override
        public String getColumnName(int columnIndex) {
            switch (columnIndex) {
            case 0:
                return columnNames[0];
            case 1:
                return columnNames[1];
            case 2:
                return columnNames[2];
            case 3:
                return columnNames[3];
            case 4:
                return columnNames[4];
            case 5:
                return columnNames[5];
            default:
                return null;
            }
        }

        @Override
        public int getRowCount() {
            return data[0].length - 1;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            return data[rowIndex][columnIndex];
        }

        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            switch (columnIndex) {
            case 5:
                return true;
            default:
                return false;
            }

        }

        @Override
        public void removeTableModelListener(TableModelListener l) {
        }

        @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            data[rowIndex][columnIndex] = aValue;
        }

    }

    public void centerWindow() {
        Dimension dimension = getToolkit().getScreenSize();
        setLocation(((int) dimension.getWidth()) / 2 - (getWidth() / 2),
                ((int) dimension.getHeight()) / 2 - (getHeight() / 2));
    }

}

This is the result before clicking:

在此处输入图片说明

You have to filter the object type and catch the String value before you call Object.toString(); Because Object.toString() method return details about the Object unless it is a String.

value = value instanceof JComboBox ? ((JComboBox) value).getSelectedItem().toString() : value.toString();

then you can use the value.

setText(value);

Also I noticed that you called

 table.setRowHeight((int) getPreferredSize().getHeight() + 5);

inside getTableCellRendererComponent(). Don't do that , It will recall getTableCellRendererComponent() itself again and again and it will make a stack-overflow.

Also I made some changes to the model.It had some bugs like @ getRowCount()"return data[0].length - 1;" (columns count returning instead of the row count) which has to be "return data.length;"

 @Override
        public Class<?> getColumnClass(int columnIndex) {
            Object value = this.getValueAt(0, columnIndex);
            return (value == null ? Object.class : value.getClass());
        }

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

        @Override
        public String getColumnName(int columnIndex) {
            return columnNames[columnIndex];
        }

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM