如何在现有的JTable上添加一个由JComboboxes组成的行的表

时间:2014-10-28 16:58:56

标签: java swing jtable jcombobox tablecellrenderer

我试图在现有JTable之上添加一行JTable,这通常是动态创建的,并且经常更改其数据模型。

JTable

如您所见,黄色区域仅代表行计数器,并且已使用此source

创建

因此,黄色列已使用以下代码附加到主表:

JTable rowTable = new RowNumberTable(table);
scrollTable.setRowHeaderView(rowTable);

表列A,B,C等,如果单击,则相应地对JTable进行排序,并且应该维护此功能(除非有一个聪明的方法,否则我不想将JCombobox放在表头中这两件事。)

我的目标是创建一个具有一行的JTable(参见红色行),其中包含与主JTable一样多的列

修改

这里有 SSCCE

我想把JComboBox放在A,B,C,D ......

之上

呈现JComboBox的类是ColumnJComboBoxTable,在TableDemo中调用如下:

//Column JCombobox
JTable columnTable = new ColumnJComboBoxTable(table);
scrollTable.setColumnHeaderView(columnTable);

现在它没有按照我想要的方式工作(嗯,根本不起作用)

enter image description here

顶部的按钮添加和删除列。因此,如果删除列,则必须删除相应的JComboBox。

CODE

TableDemo

package com.table;
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.AbstractAction;

public class TableDemo extends JFrame 
{

private static final long serialVersionUID = 1L;

public TableDemo() 
{
    super("TableDemo");

    Object[][] data = 
    {
        {"0","1","2","3","4","5","6","7","8","9","10"},
        {"0","1","2","3","4","5","6","7","8","9","10"},
        {"0","1","2","3","4","5","6","7","8","9","10"},
        {"0","1","2","3","4","5","6","7","8","9","10"},
        {"0","1","2","3","4","5","6","7","8","9","10"},
        {"0","1","2","3","4","5","6","7","8","9","10"},
        {"0","1","2","3","4","5","6","7","8","9","10"},
        {"0","1","2","3","4","5","6","7","8","9","10"},
        {"0","1","2","3","4","5","6","7","8","9","10"},
        {"0","1","2","3","4","5","6","7","8","9","10"},
        {"0","1","2","3","4","5","6","7","8","9","10"},
        {"0","1","2","3","4","5","6","7","8","9","10"},
        {"0","1","2","3","4","5","6","7","8","9","10"},
        {"0","1","2","3","4","5","6","7","8","9","10"},
    };

    String[] columnNames = 
    {       
                "A", 
                "B", 
                "C", 
                "D", 
                "E", 
                "F", 
                "G", 
                "H",
                "I", 
                "J",
                "K",
    };

    final JTable            table       = new JTable(data, columnNames);
    new JPopupMenu();
    final JToolBar          toolBar     = new JToolBar();
    final XTableColumnModel columnModel = new XTableColumnModel();

    table.setColumnModel(columnModel);
    table.createDefaultColumnsFromModel();

    toolBar.add(new JButton(new AbstractAction("ALL") {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e) {
            columnModel.setAllColumnsVisible();
        }
    }));

    toolBar.add(new JButton(new AbstractAction("Column 0") {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e) {
            TableColumn column  = columnModel.getColumnByModelIndex(0);
            boolean     visible = columnModel.isColumnVisible(column);
            columnModel.setColumnVisible(column, !visible);
        }
    }));
    toolBar.add(new JButton(new AbstractAction("Column 1") {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e) {
            TableColumn column  = columnModel.getColumnByModelIndex(1);
            boolean     visible = columnModel.isColumnVisible(column);
            columnModel.setColumnVisible(column, !visible);
        }
    }));
    toolBar.add(new JButton(new AbstractAction("Column 2") {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e) {
            TableColumn column  = columnModel.getColumnByModelIndex(2);
            boolean     visible = columnModel.isColumnVisible(column);
            columnModel.setColumnVisible(column, !visible);
        }
    }));
    toolBar.add(new JButton(new AbstractAction("Column 3") {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e) {
            TableColumn column  = columnModel.getColumnByModelIndex(3);
            boolean     visible = columnModel.isColumnVisible(column);
            columnModel.setColumnVisible(column, !visible);
        }
    }));

    toolBar.add(new JButton(new AbstractAction("Column 4") {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e) {
            TableColumn column  = columnModel.getColumnByModelIndex(4);
            boolean     visible = columnModel.isColumnVisible(column);
            columnModel.setColumnVisible(column, !visible);
        }
    }));
    toolBar.add(new JButton(new AbstractAction("Column 5") {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e) {
            TableColumn column  = columnModel.getColumnByModelIndex(5);
            boolean     visible = columnModel.isColumnVisible(column);
            columnModel.setColumnVisible(column, !visible);
        }
    }));
    toolBar.add(new JButton(new AbstractAction("Column 6") {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e) {
            TableColumn column  = columnModel.getColumnByModelIndex(6);
            boolean     visible = columnModel.isColumnVisible(column);
            columnModel.setColumnVisible(column, !visible);
        }
    }));
    toolBar.add(new JButton(new AbstractAction("Column 7") {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e) {
            TableColumn column  = columnModel.getColumnByModelIndex(7);
            boolean     visible = columnModel.isColumnVisible(column);
            columnModel.setColumnVisible(column, !visible);
        }
    }));
    toolBar.add(new JButton(new AbstractAction("Column 8") {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e) {
            TableColumn column  = columnModel.getColumnByModelIndex(8);
            boolean     visible = columnModel.isColumnVisible(column);
            columnModel.setColumnVisible(column, !visible);
        }
    }));
    toolBar.add(new JButton(new AbstractAction("Column 9") {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e) {
            TableColumn column  = columnModel.getColumnByModelIndex(9);
            boolean     visible = columnModel.isColumnVisible(column);
            columnModel.setColumnVisible(column, !visible);
        }
    }));
    toolBar.add(new JButton(new AbstractAction("Column 10") {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e) {
            TableColumn column  = columnModel.getColumnByModelIndex(10);
            boolean     visible = columnModel.isColumnVisible(column);
            columnModel.setColumnVisible(column, !visible);
        }
    }));


    //Row number
    table.setFillsViewportHeight(true);
    JScrollPane scrollTable = new JScrollPane(table,
                JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    scrollTable.setViewportView(table);

    JTable rowTable = new RowNumberTable(table);
    scrollTable.setRowHeaderView(rowTable);
    scrollTable.setCorner(JScrollPane.UPPER_LEFT_CORNER, rowTable.getTableHeader());

    //Column JCombobox
    JTable columnTable = new ColumnJComboBoxTable(table);
    scrollTable.setColumnHeaderView(columnTable);

    getContentPane().add(toolBar,       BorderLayout.NORTH);
    getContentPane().add(scrollTable,    BorderLayout.CENTER);

    addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent e) {
            System.exit(0);
        }
    });
}

public static void main(String[] args) 
{
    TableDemo frame = new TableDemo();

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

XTableColumnModel

借用了表格模型here

package com.table;
import javax.swing.table.*;
import java.util.Vector;
import java.util.Enumeration;


public class XTableColumnModel extends DefaultTableColumnModel {

private static final long serialVersionUID = 1L;

protected Vector allTableColumns            = new Vector();

XTableColumnModel() {
}

public void setColumnVisible(TableColumn column, boolean visible) {
    if(!visible) {
        super.removeColumn(column);
    }
    else 
    {
        int noVisibleColumns    = tableColumns.size();
        int noInvisibleColumns  = allTableColumns.size();
        int visibleIndex        = 0;

        for(int invisibleIndex = 0; invisibleIndex < noInvisibleColumns; ++invisibleIndex) {
            TableColumn visibleColumn   = (visibleIndex < noVisibleColumns ? (TableColumn)tableColumns.get(visibleIndex) : null);
            TableColumn testColumn      = (TableColumn)allTableColumns.get(invisibleIndex);

            if(testColumn == column) {
                if(visibleColumn != column) {
                    super.addColumn(column);
                    super.moveColumn(tableColumns.size() - 1, visibleIndex);
                }
                return;
            }
            if(testColumn == visibleColumn) {
                ++visibleIndex;
            }
        }
    }
}

public void setAllColumnsVisible() {
    int noColumns       = allTableColumns.size();

    for(int columnIndex = 0; columnIndex < noColumns; ++columnIndex) {
        TableColumn visibleColumn = (columnIndex < tableColumns.size() ? (TableColumn)tableColumns.get(columnIndex) : null);
        TableColumn invisibleColumn = (TableColumn)allTableColumns.get(columnIndex);

        if(visibleColumn != invisibleColumn) {
            super.addColumn(invisibleColumn);
            super.moveColumn(tableColumns.size() - 1, columnIndex);
        }
    }
}

public TableColumn getColumnByModelIndex(int modelColumnIndex) {
    for (int columnIndex = 0; columnIndex < allTableColumns.size(); ++columnIndex) {
        TableColumn column = (TableColumn)allTableColumns.elementAt(columnIndex);
        if(column.getModelIndex() == modelColumnIndex) {
            return column;
        }
    }
    return null;
}

public boolean isColumnVisible(TableColumn aColumn) {
    return (tableColumns.indexOf(aColumn) >= 0);
}

public void addColumn(TableColumn column) {
    allTableColumns.addElement(column);
    super.addColumn(column);
}

public void removeColumn(TableColumn column) {
    int allColumnsIndex = allTableColumns.indexOf(column);
    if(allColumnsIndex != -1) {
        allTableColumns.removeElementAt(allColumnsIndex);
    }
    super.removeColumn(column);
}

public void moveColumn(int oldIndex, int newIndex) {
if ((oldIndex < 0) || (oldIndex >= getColumnCount()) ||
    (newIndex < 0) || (newIndex >= getColumnCount()))
    throw new IllegalArgumentException("moveColumn() - Index out of range");

    TableColumn fromColumn  = (TableColumn) tableColumns.get(oldIndex);
    TableColumn toColumn    = (TableColumn) tableColumns.get(newIndex);

    int allColumnsOldIndex  = allTableColumns.indexOf(fromColumn);
    int allColumnsNewIndex  = allTableColumns.indexOf(toColumn);

    if(oldIndex != newIndex) {
        allTableColumns.removeElementAt(allColumnsOldIndex);
        allTableColumns.insertElementAt(fromColumn, allColumnsNewIndex);
    }

    super.moveColumn(oldIndex, newIndex);
}

public int getColumnCount(boolean onlyVisible) {
    Vector columns = (onlyVisible ? tableColumns : allTableColumns);
return columns.size();
}

public Enumeration getColumns(boolean onlyVisible) {
    Vector columns = (onlyVisible ? tableColumns : allTableColumns);

return columns.elements();
}

public int getColumnIndex(Object identifier, boolean onlyVisible) {
if (identifier == null) {
    throw new IllegalArgumentException("Identifier is null");
}

    Vector      columns     = (onlyVisible ? tableColumns : allTableColumns);
    int         noColumns   = columns.size();
    TableColumn column;

    for(int columnIndex = 0; columnIndex < noColumns; ++columnIndex) {
    column = (TableColumn)columns.get(columnIndex);

        if(identifier.equals(column.getIdentifier()))
    return columnIndex;
    }

throw new IllegalArgumentException("Identifier not found");
}

public TableColumn getColumn(int columnIndex, boolean onlyVisible) {
return (TableColumn)tableColumns.elementAt(columnIndex);
}
}

RowNumberTable

package com.table;
import java.awt.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;


public class RowNumberTable extends JTable
implements ChangeListener, PropertyChangeListener, TableModelListener
{

private static final long serialVersionUID = -3837585325898676144L;
private JTable main;

public RowNumberTable(JTable table)
{
    main = table;
    main.addPropertyChangeListener( this );
    main.getModel().addTableModelListener( this );

    setFocusable( false );
    setAutoCreateColumnsFromModel( false );
    setSelectionModel( main.getSelectionModel() );

    TableColumn column = new TableColumn();
    column.setHeaderValue(" ");
    addColumn( column );
    column.setCellRenderer(new RowNumberRenderer());

    getColumnModel().getColumn(0).setPreferredWidth(50);
    setPreferredScrollableViewportSize(getPreferredSize());
}

@Override
public void addNotify()
{
    super.addNotify();

    Component c = getParent();

    //  Keep scrolling of the row table in sync with the main table.

    if (c instanceof JViewport)
    {
        JViewport viewport = (JViewport)c;
        viewport.addChangeListener( this );
    }
}


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

@Override
public int getRowHeight(int row)
{
    int rowHeight = main.getRowHeight(row);

    if (rowHeight != super.getRowHeight(row))
    {
        super.setRowHeight(row, rowHeight);
    }

    return rowHeight;
}


@Override
public Object getValueAt(int row, int column)
{
    return Integer.toString(row + 1);
}


@Override
public boolean isCellEditable(int row, int column)
{
    return false;
}

@Override
public void setValueAt(Object value, int row, int column) {}

public void stateChanged(ChangeEvent e)
{
    //  Keep the scrolling of the row table in sync with main table

    JViewport viewport = (JViewport) e.getSource();
    JScrollPane scrollPane = (JScrollPane)viewport.getParent();
    scrollPane.getVerticalScrollBar().setValue(viewport.getViewPosition().y);
    viewport.setBackground(Color.WHITE);
}

public void propertyChange(PropertyChangeEvent e)
{
    //  Keep the row table in sync with the main table

    if ("selectionModel".equals(e.getPropertyName()))
    {
        setSelectionModel( main.getSelectionModel() );
    }

    if ("rowHeight".equals(e.getPropertyName()))
    {
        repaint();
    }

    if ("model".equals(e.getPropertyName()))
    {
        main.getModel().addTableModelListener( this );
        revalidate();
    }
}

@Override
public void tableChanged(TableModelEvent e)
{
    revalidate();
}

/*
 *  Attempt to mimic the table header renderer
 */
private static class RowNumberRenderer extends DefaultTableCellRenderer
{
    /**
     * 
     */
    private static final long serialVersionUID = 6579115025835194953L;

    public RowNumberRenderer()
    {
        setHorizontalAlignment(JLabel.CENTER);
    }

    public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    {
        if (table != null)
        {
            JTableHeader header = table.getTableHeader();

            if (header != null)
            {
                setForeground(header.getForeground());
                setBackground(header.getBackground());
                setFont(header.getFont());
            }
        }

        if (isSelected)
        {
            setFont( getFont().deriveFont(Font.ITALIC) );
        }

        setText((value == null) ? "" : value.toString());
        //setBorder(UIManager.getBorder("TableHeader.cellBorder"));

        return this;
    }
  }
}

ColumnJComboBoxTable

package com.table;
import java.awt.*;
import java.beans.*;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;


public class ColumnJComboBoxTable extends JTable implements ChangeListener,PropertyChangeListener, TableModelListener
{

private static final long serialVersionUID = -3837585325898676144L;
private JTable main;

public ColumnJComboBoxTable(JTable table)
{
    main = table;
    main.addPropertyChangeListener( this );
    main.getModel().addTableModelListener( this );

    setFocusable( false );
    setAutoCreateColumnsFromModel( false );
    setSelectionModel( main.getSelectionModel() );

    for(int i =0; i<main.getModel().getColumnCount();i++)
    {
        TableColumn column = new TableColumn();
        column.setHeaderValue(i);
        addColumn( column );
        getColumnModel().getColumn(i).setPreferredWidth(50);
        column.setCellRenderer(new ColumnJComboBoxRenderer());
        column.setHeaderRenderer(new ColumnJComboBoxRenderer());
    }
    setPreferredScrollableViewportSize(getPreferredSize());

}

@Override
public void addNotify()
{
    super.addNotify();

    Component c = getParent();

    //  Keep scrolling of the row table in sync with the main table.

    if (c instanceof JViewport)
    {
        JViewport viewport = (JViewport)c;
        viewport.addChangeListener( this );
    }
}

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

@Override
public int getRowHeight(int row)
{
    int rowHeight = main.getRowHeight(row);

    if (rowHeight != super.getRowHeight(row))
    {
        super.setRowHeight(row, rowHeight);
    }
    return rowHeight;
}

/*
 *  No model is being used for this table so just use the row number
 *  as the value of the cell.
 */
@Override
public Object getValueAt(int row, int column)
{
    return Integer.toString(column + 1);
}

/*
 *  Don't edit data in the main TableModel by mistake
 */
@Override
public boolean isCellEditable(int row, int column)
{
    return false;
}

/*
 *  Do nothing since the table ignores the model
 */

@Override
public void setValueAt(Object value, int row, int column) {}
//
//  Implement the ChangeListener
//
public void stateChanged(ChangeEvent e)
{
    //  Keep the scrolling of the row table in sync with main table
    JViewport viewport = (JViewport) e.getSource();
    JScrollPane scrollPane = (JScrollPane)viewport.getParent();
    scrollPane.getHorizontalScrollBar().setValue(viewport.getViewPosition().x);
}

//
//  Implement the PropertyChangeListener
//

public void propertyChange(PropertyChangeEvent e)
{
    //  Keep the row table in sync with the main table

    if ("selectionModel".equals(e.getPropertyName()))
    {
        setSelectionModel( main.getSelectionModel() );
    }

    if ("rowHeight".equals(e.getPropertyName()))
    {
        repaint();
    }

    if ("model".equals(e.getPropertyName()))
    {
        main.getModel().addTableModelListener( this );
        revalidate();
    }
}

//
//  Implement the TableModelListener
//
@Override
public void tableChanged(TableModelEvent e)
{
    revalidate();
}

/*
 *  Attempt to mimic the table header renderer
 */
private static class ColumnJComboBoxRenderer extends DefaultTableCellRenderer
{
    /**
     * 
     */
    private static final long serialVersionUID = 6579115025835194953L;

    public ColumnJComboBoxRenderer()
    {
        setHorizontalAlignment(JLabel.HORIZONTAL);
    }

    public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    {
        if (table != null)
        {
            JTableHeader header = table.getTableHeader();

            if (header != null)
            {
                setForeground(header.getForeground());
                setBackground(header.getBackground());
                setFont(header.getFont());
            }
        }

        if (isSelected)
        {
            setFont( getFont().deriveFont(Font.ITALIC) );
        }
        setText((value == null) ? "" : value.toString());

        return this;
    }
  }
}

任何人的帮助都将受到高度赞赏

由于

1 个答案:

答案 0 :(得分:1)

感谢@mKorbel的帮助

这里是解决方案的代码

import java.awt.*;
import javax.swing.*; 
import javax.swing.event.*;
import javax.swing.table.*;

public class TableFilterRow implements TableColumnModelListener
{

private JTable table;
private JPanel filterRow;

public TableFilterRow(JTable table,JPanel filterRow) 
{
    this.table = table;
    this.filterRow=filterRow;
    table.setPreferredScrollableViewportSize(table.getPreferredSize());
    table.getColumnModel().addColumnModelListener(this);
    table.columnMarginChanged(new ChangeEvent(table.getColumnModel()));
}

@Override
public void columnMarginChanged(ChangeEvent e) 
{
    TableColumnModel tcm = table.getColumnModel();

    int columns = tcm.getColumnCount();

    for (int i = 0; i < columns; i++)
    {
        JComboBox<?> comboBox = (JComboBox<?>) filterRow.getComponent(i);
        Dimension d = comboBox.getPreferredSize();
        d.width = tcm.getColumn(i).getWidth();
        comboBox.setPreferredSize(d);
    }

    SwingUtilities.invokeLater(new Runnable() 
    {
        @Override
        public void run() 
        {
        filterRow.revalidate();
        }
    });
}

@Override
public void columnMoved(TableColumnModelEvent e) 
{
     Component moved = filterRow.getComponent(e.getFromIndex());
     filterRow.remove(e.getFromIndex());
     filterRow.add(moved, e.getToIndex());
     filterRow.validate();
}

@Override
public void columnAdded(TableColumnModelEvent e) 
{

}

@Override
public void columnRemoved(TableColumnModelEvent e) 
{

}

@Override
public void columnSelectionChanged(ListSelectionEvent e) 
{

}

public static void main(String[] args) 
{
    JFrame frame = new JFrame();
    frame.setLayout(new BorderLayout());
    JTable table = new JTable(3, 5);
    table.setPreferredScrollableViewportSize(table.getPreferredSize());
    table.columnMarginChanged(new ChangeEvent(table.getColumnModel()));

    ComboFields[] comboFields = ComboFields.values();

    JScrollPane scrollPane = new JScrollPane(table);
    frame.add(scrollPane, BorderLayout.CENTER);

    JPanel filterRow = new JPanel();
    filterRow.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));

    for (int i = 0; i < table.getColumnCount(); i++) 
    {
        filterRow.add(new JComboBox<ComboFields>(comboFields));
    }
    new TableFilterRow(table, filterRow);

    frame.add(filterRow, BorderLayout.NORTH);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
}

private enum ComboFields{

    VALUE_0(0), 
    VALUE_1(1),
    VALUE_2(2),
    VALUE_3(3),
    VALUE_4(4),
    VALUE_5(5);
    // Internal state
    private int fieldNumber;

    private ComboFields(final int fieldNumber) 
    {
        this.setFieldNumber(fieldNumber);
    }

    @SuppressWarnings("unused")
    public int getFieldNumber() {
        return fieldNumber;
    }

    public void setFieldNumber(int fieldNumber) 
    {
        this.fieldNumber = fieldNumber;
    }
  }
}