Skip to main content

Running into problems with DefaultTabelCellRenderer and JXTable

1 reply [Last post]
Bratmaxxe
Offline
Joined: 2011-04-15
Points: 0

Hello everybody,
i just switched to the JXTable but ran into some problems, when using DefaultTableCellRenderer.
See example below:

import java.awt.BorderLayout;
import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.jdesktop.swingx.decorator.HighlightPredicate;
import org.jdesktop.swingx.decorator.HighlighterFactory;

@SuppressWarnings("serial")
public class DiskTable extends JFrame {

    public DiskTable()
    {
        List<Disk> list = new ArrayList<Disk>();
        list.add(new CD("TrulaTrula", "????"));
        list.add(new CD("Titel1", "X"));
        list.add(new CD("Titel2", "X"));
        list.add(new DVD("Titel4", "Y"));
        list.add(new CD("Titel5", "Z"));
        list.add(new DVD("Titel6", "X"));
      
        JXTable table = new JXTable(new DiskModel(list));
        table.putClientProperty(JXTable.USE_DTCR_COLORMEMORY_HACK, null);
      
        TableColumn col = table.getColumnModel().getColumn(1);
        col.setCellRenderer(new StringColorCellRenderer("X", Color.GREEN));
      
        ColorHighlighter rollover = new ColorHighlighter(HighlightPredicate.ROLLOVER_ROW, null, Color.BLUE);
        table.setHighlighters(HighlighterFactory.createAlternateStriping(Color.WHITE, HighlighterFactory.QUICKSILVER), rollover);
        table.setColumnControlVisible(true);
      
        this.getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
    }

    class DiskModel extends AbstractTableModel {

        private List<Disk> list;

        public DiskModel(List<Disk> list)
        {
            this.list = list;
        }

        public String getColumnName(int column)
        {
            switch (column)
            {
                case 0:
                    return "Titel";
                case 1:
                    return "Interpret";
                case 2:
                    return "Typ";
            }
            return "";
        }

        public Object getValueAt(int row, int column)
        {
            Disk disk = list.get(row);
            switch (column)
            {
                case 0:
                    return disk.getTitle();
                case 1:
                    return disk.getInterpret();
                case 2:
                    return disk.getType();
            }
            return null;
        }

        public int getColumnCount()
        {
            return 3;
        }

        public int getRowCount()
        {
            return list.size();
        }
    }

    class CD extends Disk {

        public CD(String title, String interpret)
        {
            super(title, interpret);
        }
    }

    class DVD extends Disk {

        public DVD(String title, String interpret)
        {
            super(title, interpret);
        }
    }

    abstract class Disk {

        private String title, interpret;

        public Disk(String title, String interpret)
        {
            this.title = title;
            this.interpret = interpret;
        }

        public String getTitle()
        {
            return title;
        }

        public String getInterpret()
        {
            return interpret;
        }

        public String getType()
        {
            return this.getClass().getSimpleName();
        }
    }

    public static void main(String[] args)
    {
        JFrame frame = new DiskTable();
        frame.setBounds(0, 0, 500, 300);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}
import java.awt.Color;
import java.awt.Component;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;

public class StringColorCellRenderer extends DefaultTableCellRenderer {

    private static final long serialVersionUID = 1L;
    private int layout;
    private String containsString;
    private Color farbe;

    public StringColorCellRenderer(String containsString, Color farbe)
    {
        this.containsString = containsString;
        this.farbe = farbe;
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    {
        Component cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

        if (cell instanceof JLabel)
        {
            JLabel label = (JLabel) cell;
            label.setHorizontalAlignment(layout);
        }

        if (value.equals(containsString))
        {
            cell.setBackground(farbe);
        } else
        {
            if (hasFocus || isSelected)
            {
                cell.setBackground(table.getSelectionBackground());
            } else
            {
                cell.setBackground(table.getBackground());
            }
        }

        return cell;
    }

    public void setComponentLayout(int layout)
    {
        this.layout = layout;
    }
}

First problem was "coloring of specific table cells, if they contain a special string":
- solved it with (Posting on Jira: http://java.net/jira/browse/SWINGX-1390): table.putClientProperty(JXTable.USE_DTCR_COLORMEMORY_HACK, null);
==Quote==
Karl Schaefer added a comment - 01/Feb/11 09:52 AM
First, SwingX suggests not using TableCellRenderers that are a subclass of DefaultTableCellRenderer. It is a poor implementation of a renderer and it also does not take advantage of the SwingX rendering paradigm of StringValues (for display text) and Highlighters for visual decoration. I'd recommend replacing your custom DTCR subclass with a DefaultTableRenderer that Highlighters, such as HighlighterFactory.createAlternateStriping().
Second, if you continue using the DTCR subclass and it handles colors correctly (because DTCR does not), you may need to call JXTable.putClientProperty(JXTable.USE_DTCR_COLORMEMORY_HACK, null). This should causes JXTable to honor your colors.
==Quote==

But there is i negative side effect if i use a ColorHighlighter for MouseOver in the JXTable (just try the code above), on mouse over all columns are marked...
So there are much renderers which are subclassed by DefaultTableCellRenderer, for example setting a special Font for a specific Column. I can not use a DefaultTableRenderer in that class, bcs. there is no setFont Method:

import java.awt.Font;
import javax.swing.table.DefaultTableCellRenderer;

public class FontCellRenderer extends DefaultTableCellRenderer {

    private static final long serialVersionUID = 1L;

    private Font customFont;

    public FontCellRenderer(Font customFont)
    {
        this.customFont = customFont;
        setFont(customFont);
    }

    @Override
    public Font getFont()
    {
        return customFont;
    }
  
}

A bypass would be: table.setFont()
But DefaultTableCellRenderer supports also the alignment of the string.... (new FontCellRenderer().setHorizontalAlignment();)
How can i achieve that when using DefaultTableRenderer - solving one problem causes some more problems!
Which way do u prefer for renderering - and what is the right way for doing this, respectively using jxtable ?
Sincerely, Bratmaxxe

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
kschaefe
Offline
Joined: 2006-06-08
Points: 0

Use FontHighlighter to set the font and either ColumnPredicate to have a fixed set of columns to highlight or RolloverColumn to highlight the moused column or RolloverCell to highlight only the specific cell. As for alignment setting that is done via the ComponentProvider, most likely the LabelProvider in your case.

Karl