Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
274 views
in Technique[技术] by (71.8m points)

java - Exclude a column from JTable when sorting

So I basically do not want the second column to show up when I sort in my JTable or vice-versa. A picture is worth a thousands words so here is a picture to show you what I mean. http://i48.tinypic.com/2rzpfe9.jpg So as you can see when I search for the word "apple" in my JTable, the second column is still there which it shouldn't be because the first column has the word "apple" in it and not the second column. So how can I make it that that the other column don't show up or vice-versa?

EDIT : I have edited the code below to match what MadProgrammer said but it still isn't working right. New pic http://i48.tinypic.com/2rzpfe9.jpg The text this time is gone but the column remains. What am I doing wrong this time?

    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.ImageIcon;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.JTextArea;
    import javax.swing.JTextField;
    import javax.swing.RowFilter;
    import javax.swing.UIManager;
    import javax.swing.border.EmptyBorder;
    import javax.swing.table.DefaultTableModel;
    import javax.swing.table.TableCellRenderer;
    import javax.swing.table.TableColumn;
    import javax.swing.table.TableModel;
    import javax.swing.table.TableRowSorter;

public class sorter extends JFrame {
/**
     * 
     */
private static final long serialVersionUID = 1L;
public sorter() {
initComponents();
panel.setLayout(null);
search.setBounds(30,10,400,25);
search_button.setBounds(430,10,30,25);
}
public class FilterEntry extends RowFilter.Entry<TableModel, Integer> {

    private final TableModel model;
    private final Object value;
    private final int rowIndex;

    public FilterEntry(TableModel model, Object value, int rowIndex) {

        this.model = model;
        this.value = value;
        this.rowIndex = rowIndex;

    }

    @Override
    public TableModel getModel() {

        return model;

    }

    @Override
    public int getValueCount() {

        return getModel().getColumnCount();

    }

    @Override
    public Object getValue(int index) {

        return value;

    }

    @Override
    public Integer getIdentifier() {

        return rowIndex;

    }

}


private void initComponents() {
panel = new JPanel();
logo = new JLabel();
pane = new JScrollPane();
search = new JTextField();
search_button = new JButton();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBackground(new Color(255, 255, 204));
setResizable(false);
panel.setBackground(new Color(51, 51, 51));
panel.setPreferredSize(new Dimension(290, 40));
javax.swing.GroupLayout panelLayout = new javax.swing.GroupLayout(panel);
panel.setLayout(panelLayout);
panelLayout.setHorizontalGroup(
panelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelLayout.createSequentialGroup()
.addGap(198, 198, 198)
.addComponent(logo)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
panelLayout.setVerticalGroup(
panelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelLayout.createSequentialGroup()
.addContainerGap(0, Short.MAX_VALUE)
.addComponent(logo)
.addContainerGap())
);
search.setText("");
search.setToolTipText("");
search.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.LOWERED));
search.setPreferredSize(new java.awt.Dimension(30, 15));
search_button.setIcon(new javax.swing.ImageIcon(getClass().getResource("/search.JPG"))); // NOI18N
search_button.setAlignmentY(0.0F);
search_button.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));
search_button.setContentAreaFilled(false);
search_button.setIconTextGap(1);
search_button.setMargin(new java.awt.Insets(1, 4, 1, 4));
search_button.setMaximumSize(new java.awt.Dimension(5, 30));
search_button.setMinimumSize(new java.awt.Dimension(5, 30));
search_button.setPreferredSize(new java.awt.Dimension(30, 20));
javax.swing.GroupLayout panelLayout1 = new javax.swing.GroupLayout(panel);
panel.setLayout(panelLayout1);
panelLayout1.setHorizontalGroup(
panelLayout1.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelLayout1.createSequentialGroup()
.addGroup(panelLayout1.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelLayout1.createSequentialGroup()
.addGap(25, 25, 25)
.addComponent(search, javax.swing.GroupLayout.PREFERRED_SIZE, 400, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0)
.addComponent(search_button, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(panelLayout1.createSequentialGroup()
.addGap(174, 174, 174)
.addComponent(logo)))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
panelLayout1.setVerticalGroup(
panelLayout1.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelLayout1.createSequentialGroup()
.addGap(5, 5, 5)
.addComponent(logo)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(panelLayout1.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(search, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(search_button, javax.swing.GroupLayout.PREFERRED_SIZE, 26, Short.MAX_VALUE))
.addContainerGap())
);
ImageIcon Icon1 = getImage("lemon.jpg");
ImageIcon Icon2 = getImage("az.jpg");
ImageIcon Icon3 = getImage("aaa.jpg");
ImageIcon Icon4 = getImage("ba.jpg");
ImageIcon Icon5 = getImage("bas.jpg");
ImageIcon Icon6 = getImage("cookies.jpg");
String[] columnNames = {"A", "Section 1","B", "Section 2"};
Object[][] data =
{
{Icon1, "Lemon", Icon2, "Grapes"},
{Icon3, "Apple", Icon4, "Banana"},
{Icon5, "Orange", Icon6, "Cookies"},
};
DefaultTableModel model = new DefaultTableModel(data, columnNames);
JTable table = new JTable(model)
{
/**
     * 
     */
    private static final long serialVersionUID = 1L;
@SuppressWarnings({ "unchecked", "rawtypes" })
public Class getColumnClass(int column)
{
return getValueAt(0, column).getClass();
}
public boolean isCellEditable(int row, int col) {
return false;
}
};
class MultiLineCellRenderer extends JTextArea implements TableCellRenderer {
/**
     * 
     */
private static final long serialVersionUID = 1L;
public MultiLineCellRenderer() {
setLineWrap(true);
setWrapStyleWord(true);
setOpaque(true);
}


public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected, boolean hasFocus, int row, int column) {
RowFilter rowFilter = ((TableRowSorter) table.getRowSorter()).getRowFilter();
if (rowFilter != null) {
if (!rowFilter.include(new FilterEntry(table.getModel(), value, row))) {
value = null;
}         
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
}
setFont(table.getFont());
if (hasFocus) {
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
if (table.isCellEditable(row, column)) {
setForeground(UIManager.getColor("Table.focusCellForeground"));
setBackground(UIManager.getColor("Table.focusCellBackground"));
}
} else {
setBorder(new EmptyBorder(1, 2, 1, 2));
}
setText((value == null) ? "" : value.toString());
return this;
}
}


// Sorter Code. 
table = new JTable(model);
final TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);

table.setRowSorter(sorter);
search_button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String text = search.getText();
if (text.length() == 0) {
sorter.setRowFilter(null);
} else {
sorter.setRowFilter(RowFilter.regexFilter("(?i)"+ text));
}
}
});
// sorter code ends here.



table.setRowHeight(50);
pane.setViewportView(table);
table.setBackground(new Color(255, 255, 204));
table.setDefaultRenderer(String.class, new MultiLineCellRenderer());

table.getColumnModel().getColumn(1).setCellRenderer(new MultiLineCellRenderer());
table.getColumnModel().getColumn(3).setCellRenderer(new MultiLineCellRenderer());

table.getColumnModel().getColumn(0).setResizable(false);
table.getColumnModel().getColumn(1).setResizable(false);
table.getColumnModel().getColumn(2).setResizable(false);
table.getColumnModel().getColumn(3).setResizable(false);
table.setFocusable(false);
table.setRowSelectionAllowed(false);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
int vColIndex = 0;
TableColumn col = table.getColumnModel().getColumn(vColIndex);
int width = 33;
col.setPreferredWidth(width);
int vColIndex1 = 1;
TableColumn col1 = table.getColumnModel().getColumn(vColIndex1);
int width1 = 216;
col1.setPreferredWidth(width1);
int vColIndex11 = 2;
TableColumn col11 = table.getColumnModel().getColumn(vColIndex11);
int width11 = 33;
col11.setPreferredWidth(width11);
int vColIndex111 = 3;
TableColumn col111 = table.getColumnModel().getColumn(vColIndex111);
int width111 = 216;
col111.setPreferredWidth(width111);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(panel, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE)
.addComponent(pane)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(panel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(pane, javax.swing.GroupLayout.PREFERRED_SIZE, 250, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)
.addGap(0, 0, Short.MAX_VALUE))
);
pack();
}
private ImageIcon getImage(String path)
{
java.net.URL url = getClass().getResource(path);
if (url != null)
return (new ImageIcon(url));
else
{
System.out.println(url);
return null;
}
}
public static void main(String args[]) {
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Windows".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(sorter.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(sorter.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(sorter.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(sorter.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new sorter().setVisible(true);
}
});
}
private JLabel logo;
private JScrollPane pane;
private JPanel panel;
private JTextField search;
private JButton search_button;
}
See Question&Answers more detail:<a href="https://stackoverflow.com/questions/12000263/exclude-a-column-from-

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You could modify the renderer so that it only displays the value if it matches the filter.

Given the fact that you are using the TableRowSorter makes it easier.

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

    RowFilter rowFilter = ((TableRowSorter) table.getRowSorter()).getRowFilter();
    if (rowFilter != null) {

        if (!rowFilter.include(new FilterEntry(table.getModel(), value, row))) {

            value = null;

        }

    }

    // The rest of the code...

}

Now, you're going to need to implement your own FilterEntry :P

public class FilterEntry extends RowFilter.Entry<TableModel, Integer> {

    private final TableModel model;
    private final Object value;
    private final int rowIndex;

    public FilterEntry(TableModel model, Object value, int rowIndex) {

        this.model = model;
        this.value = value;
        this.rowIndex = rowIndex;

    }

    @Override
    public TableModel getModel() {

        return model;

    }

    @Override
    public int getValueCount() {

        return getModel().getColumnCount();

    }

    @Override
    public Object getValue(int index) {

        return value;

    }

    @Override
    public Integer getIdentifier() {

        return rowIndex;

    }

}

And in order to get the example to work, I had to add

table.getColumnModel().getColumn(1).setCellRenderer(new MultiLineCellRenderer());
table.getColumnModel().getColumn(3).setCellRenderer(new MultiLineCellRenderer());

Under where you set the default cell renderer

UPDATED with Mutable column model

The larger problem you face is having the ability to turn columns on and off. Trashgod provided an example of this and I've included a sample model.

The next thing you need to do, is every time the filter changes, you need to run through the entire model and decide what should be include and what shouldn't.

This is how I achieved it...

First, you need to supply your own ColumnModel

// Changing the column model effects the data model as well...
TableModel model = table.getModel();
table.setColumnModel(new MutableColumnModel());
table.setModel(model);

In you action listener, after you apply the filter, you will need to call updateColumns

protected void updateColumns() {

    RowFilter rowFilter = ((TableRowSorter) tblSearch.getRowSorter()).getRowFilter();

    MutableTableColumnModel columnModel = (MutableTableColumnModel) tblSearch.getColumnModel();
    // Want to reset the columns, otherwise we run into problems doing the value
    // lookup, as the table doesn't think it exists.
    // You might be able to get around it with this instead, but we need
    // to rest the view any way...
    // columnModel.getColumnByModelIndex(col);
    columnModel.setColumnVisible(0, true);
    columnModel.setColumnVisible(1, true);
    columnModel.setColumnVisible(2, true);
    columnModel.setColumnVisible(3, true);

    if (rowFilter != null) {

        Map<Integer, Boolean> mapColumns = new HashMap<Integer, Boolean>(tblSearch.getColumnCount());
        for (int row = 0; row < tblSearch.getRowCount(); row++) {

            boolean include = includeValue(row, 1, rowFilter);
            mapColumns.put(0, include);
            mapColumns.put(1, include);

            include = includeValue(row, 3, rowFilter);
            mapColumns.put(2, include);
            mapColumns.put(3, include);

        }

        for (Integer col : mapColumns.keySet()) {

            columnModel.setColumnVisible(col, mapColumns.get(col));

        }

    }

}

protected boolean includeValue(int row, int col, RowFilter filter) {

    Object value = tblSearch.getValueAt(row, col);

    boolean include = filter.include(new FilterEntry(tblSearch.getModel(), value, row));

    System.out.println("include " + value + "; include = " + include);

    return include;

}

The MutableColumnModel

public class MutableTableColumnModel extends DefaultTableColumnModel {

    private List<TableColumn> allTableColumns;

    public MutableTableColumnModel() {

        allTableColumns = new ArrayList<TableColumn>(10);

    }

    public void setColumnVisible(int index, boolean visible) {

        setColumnVisible(getColumnByModelIndex(index), visible);

    }

    /**
     * Sets the visibility of the specified TableColumn.
     * The call is ignored if the TableColumn is not found in this column model
     * or its visibility status did not change.
     * <p>
     *
     * @param aColumn        the column to show/hide
     * @param visible its new visibility status
     */
    // listeners will receive columnAdded()/columnRemoved() event
    public void setColumnVisible(TableColumn column, boolean visible) {

        if (column != null) {

            if (!visible) {

                if (isColumnVisible(column)) {

                    super.removeColumn(column);

                }

            } else {

                // find the visible index of the column:
                // iterate through both collections of visible and all columns, counting
                // visible columns up to the one that's about to be shown again
                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;
                    }
                }
            }

        }
    }

    /**
     * Makes all columns in this model visible
     */
    public void showAllColumns() {
        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);
            }
        }
    }

    /**
     * Maps the index of the column in the table model at
     * <code>modelColumnIndex</code> to the TableColumn object.
     * There may me multiple TableColumn objects showing the same model column, though this is uncommon.
     * This method will always return the first visible or else the first invisible column with the specified index.
     * @param modelColumnIndex index of column in table model
     * @return table column object or null if no such column in this column model
     */
    public TableColumn getColumnByModelIndex(int modelColumnIndex) {
        for (int columnIndex = 0; columnIndex < allTableColumns.size(); ++columnIndex) {
            TableColumn column = (TableColumn) allTableColumns.get(columnIndex);
            if (column.getModelIndex() == modelColumnIndex) {
                return column;
            }
        }
        return null;
    }

    /** Checks wether the specified column is currently visible.
     * @param aColumn column to check
     * @return visibility of specified column (false if there is no such column at all. [It's not visible, right?])
     */
    public boolean isColumnVisible(TableColumn aColumn) {
        return (tableColumns.indexOf(aColumn) >= 0);
    }

    /** Append <code>column</code> to the right of exisiting columns.
     * Posts <code>columnAdded</code> event.
     * @param column The column to be added
     * @see #removeColumn
     * @exception IllegalArgumentException if <code>column</code> is <code>null</code>
     */
    public void addColumn(TableColumn column) {
        allTableColumns.add(column);
        super.addColumn(column);
    }

    /** Removes <code>column</code> from this column model.
     * Posts <code>columnRemoved</code> event.
     * Will do nothing if the column is not in this model.
     * @param column the column to be added
     * @see #addColumn
     */
    public void removeColumn(TableColumn column) {
        int allColumnsIndex = allTableColumns.indexOf(column);
        if (allColumnsIndex != -1) {
            allTableColumns.remove(allColumnsIndex);
        }
        super.removeColumn(column);
    }

    /** Moves the column from <code>oldIndex</code> to <code>newIndex</code>.
     * Posts  <code>columnMoved</code> event.
     * Will not move any columns if <code>oldIndex</code> equals <code>newIndex</code>.
     *
     * @param    oldIndex            index of column to be moved
     * @param    newIndex            new index of the column
     * @exception IllegalArgumentException    if either <code>oldIndex</code> or
     *                         <code>newIndex</code>
     *                        are not in [0, getColumnCount() - 1]
     */
    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.remove(allColumnsOldIndex);
            allTableColumns.add(allColumnsNewIndex, fromColumn);
        }

        super.moveColumn(oldIndex, newIndex);
    }

    /**
     * Returns the total number of columns in this model.
     *
     * @param   onlyVisible   if set only visible columns will be counted
     * @return    the number of columns in the <code>tableColumns</code> array
     * @see    #getColumns
     */
    public int getColumnCount(boolean onlyVisible) {
        List<TableColumn> columns = (onlyVisible ? tableColumns : allTableColumns);
        return columns.size();
    }

    /**
     * Returns an <code>Enumeration</code> of all the columns in the model.
     *
     * @param   onlyVisible   if set all invisible columns will be missing from the enumeration.
     * 

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...