Hi!

I have a code that generates the table with 6 columns, and 6 textfields. Textfields are used to filter the table, and they are assigned to columns. Everything works normally, but looks badly. Attached you will find a picture to see what I mean. I don't like that textfields and table columns have different sizes. How could I make them looking more accurately? I was thinking about making a second table with 6 columns, 1 row and invisible header instead of 6 textfields. However, I'm not sure that such solution would be the optimal one. Any ideas?

This is the code:

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.RowFilter;
import javax.swing.ScrollPaneConstants;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableRowSorter;

public class FilterClass extends JPanel {
    TableRowSorter rowSorter;
    private DefaultTableModel tableModel;

    public FilterClass() {
        //setLayout(new BorderLayout());
        initComponents();
        rowSorter=new TableRowSorter();
        tableModel = (DefaultTableModel) tableDetails.getModel();
        rowSorter.setModel(tableModel);
        tableDetails.setRowSorter(rowSorter);
    }

    private void initComponents() {
        JPanel panfortable = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
	c.fill = GridBagConstraints.HORIZONTAL;

        tableDetails = new javax.swing.JTable();
        txtRegNum = new javax.swing.JTextField();
        txtFirstName = new javax.swing.JTextField();
        txtLastName = new javax.swing.JTextField();
        txtProfession = new javax.swing.JTextField();
        txtSex = new javax.swing.JTextField();
        txtDateofBirth = new javax.swing.JTextField();

        tableDetails.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {...},
                {...},
                {...}
            },
            new String [] {"A",
                          "B",
                          "C",
                          "D",
                          "E",
                          "F"}
        ));

        // Set column widths
        tableDetails.setFillsViewportHeight(true);
        //tableDetails.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        TableColumn col;
        int width = 100;
        col = tableDetails.getColumnModel().getColumn(3);
        col.setPreferredWidth(width);
        col = tableDetails.getColumnModel().getColumn(5);
        col.setPreferredWidth(width);
        jScrollPane1 = new javax.swing.JScrollPane(tableDetails, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
        c.ipady = 0;
        c.weightx = 0.2;
        c.weighty = 0.0;
        //c.gridwidth = 1;
        //c.anchor = GridBagConstraints.CENTER;
        c.insets = new Insets(0,0,0,0);
        c.gridx = 0;
        c.gridy = 0;
        panfortable.add(txtRegNum, c);
        //c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.2;
        c.gridx = 1;
        c.gridy = 0;
        panfortable.add(txtFirstName, c);
        c.weightx = 0.2;
        c.gridx = 2;
        c.gridy = 0;
        panfortable.add(txtLastName, c);
        //c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.2;
        c.gridx = 3;
        c.gridy = 0;
        panfortable.add(txtProfession, c);
        //c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.2;
        c.gridx = 4;
        c.gridy = 0;
        panfortable.add(txtSex, c);
        //c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.2;
        c.gridx = 5;
        c.gridy = 0;
        panfortable.add(txtDateofBirth, c);
        //c.fill = GridBagConstraints.HORIZONTAL;
        c.ipady = 50;      //make this component tall
        c.weightx = 0.0;
        c.gridwidth = 6;
        c.insets = new Insets(5,0,0,0);
        c.gridx = 0;
        c.gridy = 1;
        panfortable.add(jScrollPane1, c);
        add(panfortable);

        txtRegNum.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                txtRegNumKeyReleased(evt);
            }
        });

        txtFirstName.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                txtFirstNameKeyReleased(evt);
            }
        });

        txtLastName.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                txtLastNameKeyReleased(evt);
            }
        });

        txtProfession.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                txtProfessionKeyReleased(evt);
            }
        });

        txtSex.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                txtSexKeyReleased(evt);
            }
        });

        txtDateofBirth.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                txtDateofBirthKeyReleased(evt);
            }
        });
    }

    private void txtRegNumKeyReleased(java.awt.event.KeyEvent evt) {
        rowSorter.setRowFilter(RowFilter.regexFilter("(?i)^"+txtRegNum.getText(), 0));
    }

    private void txtFirstNameKeyReleased(java.awt.event.KeyEvent evt) {
        rowSorter.setRowFilter(RowFilter.regexFilter("(?i)^"+txtFirstName.getText(), 1));
    }

    private void txtLastNameKeyReleased(java.awt.event.KeyEvent evt) {
        rowSorter.setRowFilter(RowFilter.regexFilter("(?i)^" +txtLastName.getText(), 2));
    }

    private void txtProfessionKeyReleased(java.awt.event.KeyEvent evt) {
        rowSorter.setRowFilter(RowFilter.regexFilter("(?i)^"+txtProfession.getText(), 3));
    }

    private void txtSexKeyReleased(java.awt.event.KeyEvent evt) {
        rowSorter.setRowFilter(RowFilter.regexFilter("(?i)^" +txtSex.getText(), 4));
    }

    private void txtDateofBirthKeyReleased(java.awt.event.KeyEvent evt) {
        rowSorter.setRowFilter(RowFilter.regexFilter("(?i)^" +txtDateofBirth.getText(), 5));
    }

    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable tableDetails;
    private javax.swing.JTextField txtRegNum;
    private javax.swing.JTextField txtFirstName;
    private javax.swing.JTextField txtLastName;
    private javax.swing.JTextField txtProfession;
    private javax.swing.JTextField txtSex;
    private javax.swing.JTextField txtDateofBirth;

}

Dani AI

Generated

A few practical ways to make the filter fields stay aligned with the table columns, and why the exception happened.

Both and gave the right directions: layout managers can align components, and keeping the filter widths in sync with the table columns is the usual fix. The IllegalArgumentException you saw (Identifier not found) simply means the code tried to look up a column by identifier and there was no match at that moment — that is why index-based access or sharing the column model is safer than relying on a string identifier.

Recommended approaches (ordered by robustness)

  • Share the table column model. Create a small one-row component (a separate table or a lightweight panel) that reuses the main table's ColumnModel. Because both controls use the same ColumnModel, column moves and resizes stay synchronized automatically. Make the auxiliary table non-editable and hide its header so it looks like a row of filters above the real table.

  • Keep your current text fields but drive their widths from the ColumnModel. Add a ColumnModel listener and, on margin/move events, update each field's preferred/maximum size to match the corresponding column width and call revalidate/repaint. Use index-based access to match columns to fields to avoid identifier-lookup failures, and defer UI changes (invokeLater) if you risk re-entrancy.

  • Use a layout manager (GroupLayout) only when column widths are fixed from code. If users will resize columns interactively, a layout-only solution will drift unless you update the layout whenever the ColumnModel changes.

Troubleshooting notes

  • Add the ColumnModel listener after the table has its model and columns created.
  • Avoid calling getColumn by string unless you know the column identifiers are set.
  • When updating sizes inside the ColumnModel listener, guard against infinite loops by comparing old/new widths and by scheduling updates on the EDT.

For this use case the cleanest, least-brittle choice is to share the ColumnModel between the visual filter row and the main table — it gives pixel-perfect alignment with minimal event plumbing.

Recommended Answers

All 6 Replies

You could add a TableColumnModelListener something like this to resize your filter fields

tableDetails.getColumnModel().addColumnModelListener(new TableColumnModelListener() {

        public void columnMarginChanged(ChangeEvent e) {
            txtRegNum.setPreferredSize(new Dimension(tableDetails.getColumn("A").getWidth(),txtRegNum.getPreferredSize().height));
            txtFirstName.setPreferredSize(new Dimension(tableDetails.getColumn("B").getWidth(),txtFirstName.getPreferredSize().height));
            txtLastName.setPreferredSize(new Dimension(tableDetails.getColumn("C").getWidth(),txtLastName.getPreferredSize().height));
            panfortable.revalidate();
        }

        public void columnAdded(TableColumnModelEvent e) {}
        public void columnRemoved(TableColumnModelEvent e) {}
        public void columnMoved(TableColumnModelEvent e) {}
        public void columnSelectionChanged(ListSelectionEvent e) {}
    });

You'll have to set your weightx=0 for those text components you want to size yourself like that, or they won't respect your preferred size setting.

Using a Map or List to associate your text fields to their respective columns would alleviate a lot of redundant code as well.

Hi! Thanks u both! I've tried inserting the code just after "tableDetails.setFillsViewportHeight(true);". Unfortunately, I've got the following errors:

Exception in thread "main" java.lang.IllegalArgumentException: Identifier not found
        at javax.swing.table.DefaultTableColumnModel.getColumnIndex(DefaultTableColumnModel.java:265)
        at javax.swing.JTable.getColumn(JTable.java:2529)
        at filetree.FilterClass$1.columnMarginChanged(FilterClass.java:76)
        at javax.swing.table.DefaultTableColumnModel.fireColumnMarginChanged(DefaultTableColumnModel.java:611)
        at javax.swing.table.DefaultTableColumnModel.propertyChange(DefaultTableColumnModel.java:675)
        at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:339)
        at javax.swing.event.SwingPropertyChangeSupport.firePropertyChange(SwingPropertyChangeSupport.java:75)
        at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:276)
        at javax.swing.table.TableColumn.firePropertyChange(TableColumn.java:261)
        at javax.swing.table.TableColumn.firePropertyChange(TableColumn.java:267)
        at javax.swing.table.TableColumn.setPreferredWidth(TableColumn.java:531)
        at filetree.FilterClass.initComponents(FilterClass.java:90)
        at filetree.FilterClass.<init>(FilterClass.java:35)
        at filetree.Form.createBaseRight(Form.java:122)
        at filetree.Form.createGUIforAdmin(Form.java:57)
        at filetree.Form.<init>(Form.java:45)
        at filetree.Form.main(Form.java:130)
Java Result: 1
BUILD SUCCESSFUL (total time: 3 seconds)

I can't understand what are the possible causes of errors. Could u help pliz?

You've used an invalid identifier to get the column. I used the column name in the code above, since the identifier defaults to the header value.

In your own code you use:

col = tableDetails.getColumnModel().getColumn(3);

in the new code it's done as

tableDetails.getColumn("A").getWidth()

just guessing that could be a place to try debugging.

Mike

[edit sorry didn't notice the reply]

Ok, thanks!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.