tags:

views:

313

answers:

4

Hi all,
I'm trying to show a marker on checkbox columns in a JTable to indicate that the value is dirty.

I'm having trouble coming up with a way to render the marker. I've tried setting an icon on the JCheckbox but this just renders the icon instead of the checkbox. I've tried using a Panel but it messes up the layout.

Does anyone have an idea what is the best way to do this?

Thanks

This is the sort of thing I've tried so far:

import java.awt.Component;

import javax.swing.Icon;
import javax.swing.JCheckBox;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.table.TableCellRenderer;

public class DirtyCheckboxRenderer extends JCheckBox implements TableCellRenderer {

    private final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);


    public DirtyCheckboxRenderer() {
        setHorizontalAlignment(SwingConstants.CENTER);
        setBorderPainted(true);
    }


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

        setForegroundColor(table, isSelected);
        setBackgroundColor(table, isSelected);
        setCheckboxState(value);
        setBorder(hasFocus);
        setDirtyMarkerIcon();

        return this;

    }


    private void setCheckboxState(Object value) {
        boolean checked = value != null && ((Boolean) value).booleanValue();
        setSelected(checked);
    }


    private void setBorder(boolean hasFocus) {
        if (hasFocus) {
            setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
        } else {
            setBorder(this.noFocusBorder);
        }
    }


    private void setForegroundColor(JTable table, boolean isSelected) {
        if (isSelected) {
            setForeground(table.getSelectionForeground());
        } else {
            setForeground(table.getForeground());
        }
    }


    private void setBackgroundColor(JTable table, boolean isSelected) {

        if (isSelected) { 
            setBackground(table.getSelectionBackground());
        } else {
            setBackground(table.getBackground());
        }

    }

    private void setDirtyMarkerIcon() {
        boolean columnIsDirty = true; //TODO 

        if (columnIsDirty) {
            Icon icon = getDirtyMarkerIcon();
            setHorizontalTextPosition(SwingConstants.TRAILING);
            setIcon(icon);
        } else {
            setIcon(null);
        }

    }


    private Icon getDirtyMarkerIcon() {

        //TODO
        return null; //
    }


} 
A: 

Hi, JTable should render a Checkbox automatically, if you return Boolean in the getColumnClass method in the TableModel.

keuleJ
Thanks keulej, but I get a checkbox ok. My problem is with displaying the icon.
Kevin Stembridge
+2  A: 

If you insist on having the 'dirty icon' show up trailing the checkbox, then you will have to use a panel.

To keep your column from having a broken layout, you should always render the icon, even if it is a transparent placeholder icon.

Tim Drisdelle
Thanks timmyd, I'll give that a try.
Kevin Stembridge
A: 

Well, a simple way is to change the text of the checkbox and prefix it with an asterisk.

Morgaelyn
+1  A: 

One convenient approach is to have DirtyCheckboxRenderer implement the Icon interface and do setIcon(this) in the constructor. The paintIcon() method gives you a reference to the component, and the x and y coordinates will correctly reflect your text position settings.

trashgod