tags:

views:

528

answers:

1

As title says, i wonder if you could you direct me to some document, or give me advice here, on designing (GUI design) form which main part is occupied by jtable, which has several filters.Main goal is to avoid visual clutter.

+3  A: 

I have implemented a simple TableFilterPanel in the past which has one JTextField per table column and performs regular expression matching when text is present in a given field. I typically lay this out as a list of vertical labels + text fields (i.e. so it's fairly compact).

My key class is called ColumnSearcher, which offers the ability to manufacture a RowFilter using the contents of the JTextField:

protected class ColumnSearcher {
    private final int[] columns;
    private final JTextField textField;

    public ColumnSearcher(int column, JTextField textField) {
        this.columns = new int[1];
        this.textField = textField;

        this.columns[0] = column;
    }

    public JTextField getTextField() {
        return textField;
    }

    public boolean isEmpty() {
        String txt = textField.getText();
        return txt == null || txt.trim().length() == 0;
    }

    /**
     * @return Filter based on the associated text field's value, or null if the text does not compile to a valid
     * Pattern, or the text field is empty / contains whitespace.
     */
    public RowFilter<Object, Object> createFilter() {
        RowFilter<Object, Object> ftr = null;

        if (!isEmpty()) {
            try {
                ftr = new RegexFilter(Pattern.compile(textField.getText(), Pattern.CASE_INSENSITIVE), columns);
            } catch(PatternSyntaxException ex) {
                // Do nothing.
            }
        }

        return ftr;
    }
}

When I wish to change the filter settings I build an "and" filter from each individual filter:

protected RowFilter<Object, Object> createRowFilter() {
    RowFilter<Object, Object> ret;
    java.util.List<RowFilter<Object, Object>> filters = new ArrayList<RowFilter<Object, Object>>(columnSearchers.length);

    for (ColumnSearcher cs : columnSearchers) {
        RowFilter<Object, Object> filter = cs.createFilter();
        if (filter != null) {
            filters.add(filter);
        }
    }

    if (filters.isEmpty()) {
        ret = NULL_FILTER;
    } else {
        ret = RowFilter.andFilter(filters);
    }

    return ret;
}

Typically I fire a PropertyChangeEvent when I wish to update the filters and have a PropertyChangeListener respond to it and rebuild my aggregate filter. You may then choose to fire the "rowFilter" PropertyChangeEvent if the user types in one of the text fields (e.g. by adding a DocumentListener to each JTextField).

Hope that helps.

Adamski
Nice one Adamski
willcodejavaforfood