JXTableSupport

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

JXTableSupport

PaulPaulsson
Hi,

i have a problem with the JXTableSupport. :-(

package z_glazedlists_test;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.table.JTableHeader;

import org.jdesktop.swingx.JXTable;

import ca.odell.glazedlists.BasicEventList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.SortedList;
import ca.odell.glazedlists.gui.TableFormat;
import ca.odell.glazedlists.swing.DefaultEventTableModel;
import ca.odell.glazedlists.swing.JXTableSupport;
import ca.odell.glazedlists.swing.TableComparatorChooser;

public class Z_glazedLists_Test {
       
        public static class Person implements Comparable<Person>{
        private String name;
        private String surname;

        public Person(String name, String surname) {
            this.name = name;
            this.surname = surname;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getSurname() {
            return surname;
        }
        public void setSurname(String surname) {
            this.surname = surname;
        }

        @Override
        public int compareTo(Person o) {
            return this.getName().compareTo(o.getName());
        }
    }

    private BasicEventList<Person> eventList = new
BasicEventList<Person>();
    private SortedList<Person> sortedList = new
SortedList<Person>(eventList);

    private java.util.List<Person> createList() {
        ArrayList<Person> list = new ArrayList<Person>();
        for (int i = 0; i < 100; i++) {
            list.add(new Person("James" + i, "Bond" + i));
        }
        return list;
    }

    public Z_glazedLists_Test() {
    }

    public static void main(String[] args) {
        new Z_glazedLists_Test().openDialog();
    }

    private void openDialog() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                initAll();
            }
        });
    }

    public void initAll() {
        JDialog d = new JDialog();
        d.addWindowListener(new WindowListener() {
                        public void windowOpened(WindowEvent e) {}
                        public void windowIconified(WindowEvent e) {}
                        public void windowDeiconified(WindowEvent e) {}
                        public void windowDeactivated(WindowEvent e) {}
                        public void windowClosing(WindowEvent e) {
                                System.exit(0);
                        }
                        public void windowClosed(WindowEvent e) {}
                        public void windowActivated(WindowEvent e) {}
                });
        d.setLayout(new BorderLayout());
        JButton refreshB = new JButton("refresh");
        d.add(refreshB, BorderLayout.NORTH);
        refreshB.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                refreshList();
            }
        });
        JXTable t = new JXTable();
        t.setSortable(false);
        t.getTableHeader().setDefaultRenderer(new
JTableHeader().getDefaultRenderer());
        t.setAutoCreateRowSorter(false);
        t.setRowSorter(null);

        d.add(new JScrollPane(t), BorderLayout.CENTER);

        String[] propertyNames = {"name", "surname"};
        String[] columnLabels = {"name", "surname"};
        boolean[] writable = {false, false};
       
        TableFormat<Person> tableFormat =
GlazedLists.<Person>tableFormat(propertyNames, columnLabels, writable);
        DefaultEventTableModel<Person> detModel = new
DefaultEventTableModel<Person>(eventList, tableFormat);
                JXTableSupport<Person> tableSupport =
JXTableSupport.<Person>install(t, eventList, detModel.getTableFormat(),
                                sortedList,
TableComparatorChooser.SINGLE_COLUMN);
        t.setModel(tableSupport.getTableModel());
        t.repaint();
       
        d.setPreferredSize(new Dimension(500, 300));
        d.pack();
        d.setVisible(true);
    }

    public void refreshList() {
        eventList.clear();
        eventList.addAll(createList());
    }
}

What's wrong with this code? Why i can't sort for surname?

Can anyone help me, or put it on the right place, so someone can help
me?
I'm using swingx-all-1.6.4 and the latest 'release' from glazedlists
(1.10).

Thanks for help so far!
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: JXTableSupport

James Lemieux
Hey Paul,

Change this part of your code:

TableFormat<Person> tableFormat = GlazedLists.<Person>tableFormat(propertyNames, columnLabels, writable);
DefaultEventTableModel<Person> detModel = new DefaultEventTableModel<Person>(eventList, tableFormat);
JXTableSupport<Person> tableSupport = JXTableSupport.<Person>install(t, eventList, detModel.getTableFormat(), sortedList, TableComparatorChooser.SINGLE_COLUMN);

to this:

TableFormat<Person> tableFormat = GlazedLists.<Person>tableFormat(propertyNames, columnLabels, writable);
JXTableSupport<Person> tableSupport = JXTableSupport.<Person>install(t, sortedList, tableFormat, sortedList, TableComparatorChooser.SINGLE_COLUMN);

2 changes you'll find:

Creating your own DefaultEventTableModel isn't necessary.JXTableSupport will do that for you with the TableFormat you defined.
The EventList acting as your data source must be *at least* as high as your SortedList within the pipeline, or higher. For you, this means you must pass in the sortedList as the EventList from which row objects are fetched. It is also possible to layer further transforms *above* the SortedList and pass one of those in as the data source. Your original code passed in eventList, which lies below the sortedList and thus the sorting was not honored.

Perhaps this is worth a small documentation update on the install method of JXTableSupport.

James

On Tue, May 12, 2015 at 7:35 AM, <[hidden email]> wrote:
Hi,

i have a problem with the JXTableSupport. :-(

package z_glazedlists_test;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.table.JTableHeader;

import org.jdesktop.swingx.JXTable;

import ca.odell.glazedlists.BasicEventList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.SortedList;
import ca.odell.glazedlists.gui.TableFormat;
import ca.odell.glazedlists.swing.DefaultEventTableModel;
import ca.odell.glazedlists.swing.JXTableSupport;
import ca.odell.glazedlists.swing.TableComparatorChooser;

public class Z_glazedLists_Test {

        public static class Person implements Comparable<Person>{
        private String name;
        private String surname;

        public Person(String name, String surname) {
            this.name = name;
            this.surname = surname;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getSurname() {
            return surname;
        }
        public void setSurname(String surname) {
            this.surname = surname;
        }

        @Override
        public int compareTo(Person o) {
            return this.getName().compareTo(o.getName());
        }
    }

    private BasicEventList<Person> eventList = new
BasicEventList<Person>();
    private SortedList<Person> sortedList = new
SortedList<Person>(eventList);

    private java.util.List<Person> createList() {
        ArrayList<Person> list = new ArrayList<Person>();
        for (int i = 0; i < 100; i++) {
            list.add(new Person("James" + i, "Bond" + i));
        }
        return list;
    }

    public Z_glazedLists_Test() {
    }

    public static void main(String[] args) {
        new Z_glazedLists_Test().openDialog();
    }

    private void openDialog() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                initAll();
            }
        });
    }

    public void initAll() {
        JDialog d = new JDialog();
        d.addWindowListener(new WindowListener() {
                        public void windowOpened(WindowEvent e) {}
                        public void windowIconified(WindowEvent e) {}
                        public void windowDeiconified(WindowEvent e) {}
                        public void windowDeactivated(WindowEvent e) {}
                        public void windowClosing(WindowEvent e) {
                                System.exit(0);
                        }
                        public void windowClosed(WindowEvent e) {}
                        public void windowActivated(WindowEvent e) {}
                });
        d.setLayout(new BorderLayout());
        JButton refreshB = new JButton("refresh");
        d.add(refreshB, BorderLayout.NORTH);
        refreshB.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                refreshList();
            }
        });
        JXTable t = new JXTable();
        t.setSortable(false);
        t.getTableHeader().setDefaultRenderer(new
JTableHeader().getDefaultRenderer());
        t.setAutoCreateRowSorter(false);
        t.setRowSorter(null);

        d.add(new JScrollPane(t), BorderLayout.CENTER);

        String[] propertyNames = {"name", "surname"};
        String[] columnLabels = {"name", "surname"};
        boolean[] writable = {false, false};

        TableFormat<Person> tableFormat =
GlazedLists.<Person>tableFormat(propertyNames, columnLabels, writable);
        DefaultEventTableModel<Person> detModel = new
DefaultEventTableModel<Person>(eventList, tableFormat);
                JXTableSupport<Person> tableSupport =
JXTableSupport.<Person>install(t, eventList, detModel.getTableFormat(),
                                sortedList,
TableComparatorChooser.SINGLE_COLUMN);
        t.setModel(tableSupport.getTableModel());
        t.repaint();

        d.setPreferredSize(new Dimension(500, 300));
        d.pack();
        d.setVisible(true);
    }

    public void refreshList() {
        eventList.clear();
        eventList.addAll(createList());
    }
}

What's wrong with this code? Why i can't sort for surname?

Can anyone help me, or put it on the right place, so someone can help
me?
I'm using swingx-all-1.6.4 and the latest 'release' from glazedlists
(1.10).

Thanks for help so far!

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Re: JXTableSupport

PaulPaulsson
In reply to this post by PaulPaulsson
Hi,

i have a custom tableheaderrenderer looks like the following:

public class PersonTableHeaderRenderer extends JPanel
implements TableCellRenderer, SortableRenderer {

private static final long serialVersionUID = 0;

public static final int LEFT = 0;
public static final int RIGHT = 1;

public static final Color selectedTopStartColor =
ColorUtil.parseHtmlColor("#D0E0F4");
public static final Color selectedTopEndColor =
ColorUtil.parseHtmlColor("#8FBBE8");
public static final Color selectedBottomStartColor =
ColorUtil.parseHtmlColor("#6AAAEB");
public static final Color selectedBottomEndColor =
ColorUtil.parseHtmlColor("#B8FAFF");

public static final Color unselectedTopStartColor = Color.WHITE;
public static final Color unselectedTopEndColor =
ColorUtil.parseHtmlColor("#F2F2F2");
public static final Color unselectedBottomStartColor =
ColorUtil.parseHtmlColor("#E8E8E8");
public static final Color unselectedBottomEndColor = Color.WHITE;

public static final Color borderMiddleColor =
ColorUtil.parseHtmlColor("#666666");
public static final Color borderVerticalColor = new Color(150, 150,
150, 150);

protected JTable table;
protected Object value;
protected boolean isSelected;
protected boolean hasFocus;
protected int row;
protected int column;

private int justification = LEFT;
private final JLabel iconLabel = new JLabel();
private Image icon = null;


/**
* Konstruktor
*/
public PersonTableHeaderRenderer(){
super();
}

/**
* Konstruktor
* @param aJustification Ausrichtung
*/
public PersonTableHeaderRenderer(int aJustification){
super();
justification = aJustification;
iconLabel.setOpaque(false);
add(iconLabel, BorderLayout.EAST);
iconLabel.setVisible(true);
}

/**
* Setzt die Ausrichtung
* @param aJustification Ausrichtung
*/
public void setJustification(int aJustification){
justification = aJustification;
}

/**
* Gibt den Text von einem Object zurück
* @param aObject Object
* @return Text
*/
public String getText(Object aObject){
return aObject.toString();
}


/**
* Zeichnet die Bar neu
* erlaubt individuelle Designs
* @param g Grafik
*/
@Override
public void paint(Graphics g){
Graphics2D g2d = (Graphics2D) g;

Color topStartColor = isSelected ? selectedTopStartColor :
unselectedTopStartColor;
Color topEndColor = isSelected ? selectedTopEndColor :
unselectedTopEndColor;
Color bottomStartColor = isSelected ? selectedBottomStartColor :
unselectedBottomStartColor;
Color bottomEndColor = isSelected ? selectedBottomEndColor :
unselectedBottomEndColor;

Dimension vSize = getSize();

int h = vSize.height;
int w = vSize.width;

int h2 = h / 2;
int h4 = h / 4;

g2d.setPaint(new GradientPaint(0, 0, topStartColor, 0, h4,
topEndColor));
g2d.fillRect(0, 0, w, h2);

g2d.setColor(topEndColor);
g2d.setPaint(new GradientPaint(0, h4 + 1, topStartColor, 0, h2,
topEndColor));

g2d.setPaint(new GradientPaint(0, h2, bottomStartColor, 0, h - 2,
bottomEndColor));
g2d.fillRect(0, h2, w, h - 2);

g2d.setColor(borderMiddleColor);
g2d.drawLine(0, h - 1, w, h - 1);

boolean isLast = column == table.getColumnCount() - 1;
if (!isLast){
g2d.setColor(borderVerticalColor);
g2d.drawLine(w - 1, 0, w - 1, h - 1);
}

String vText = getText(value);
if (vText != null){
RenderingHints rh = new
RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHints(rh);
g2d.setFont(new Font("Arial", java.awt.Font.BOLD, 20));

Rectangle2D vRectangle =
g2d.getFontMetrics().getStringBounds(vText,g2d);
int sx;
if (justification == LEFT){
sx = 5;
} else {
sx = w-((int)vRectangle.getWidth()+5);
}
int sy = h - (h-(int)vRectangle.getHeight()) / 2 -
g2d.getFontMetrics().getDescent();

g2d.setColor(Color.BLACK);
g2d.drawString(vText, sx, sy);
}

//draw icon
if (icon != null){
//optimize quality
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
//draw it
int iconWidth = icon.getWidth(this);
int iconHeight = icon.getHeight(this);
g2d.drawImage(icon, w-iconWidth-2, (h-iconHeight)/2, iconWidth,
iconHeight, this);
} else {
System.out.println("no icon declared!");
}
}

/**
* Gibt die bevorzugte Größe zurück
* @return Bevorzugte Größe
*/
@Override
public Dimension getPreferredSize(){
Dimension vDimension = super.getPreferredSize();
vDimension.height = getFont().getSize() + 6;
return vDimension;
}

/**
* Gibt den Tabellenzellen Komponent zurück
* @param table Tabelle
* @param value Wert
* @param isSelected Ist selektiert? (true / false)
* @param hasFocus Ist fokussiert? (true / fale)
* @param row Zeile
* @param column Spalte
* @return Komponent
*/
@Override
public Component getTableCellRendererComponent(JTable table, Object
value, boolean isSelected, boolean hasFocus, int row, int column){
this.table = table;
this.value = value;
this.isSelected = isSelected;
this.hasFocus = hasFocus;
this.row = row;
this.column = column;

setFont(table.getFont());

return this;
}

/**
* Setzt das Sortierungs Icon
* @param sortIcon Icon
*/
@Override
public void setSortIcon(Icon sortIcon) {
if (sortIcon == null){
icon = null;
} else {
icon = ((ImageIcon)sortIcon).getImage();
}
}

//
-----------------------------------------------------------------------
-------------------------------------------
// The following methods override the defaults for performance reasons
//
-----------------------------------------------------------------------
-------------------------------------------
@Override
public void validate(){
}

@Override
public void revalidate(){
}

@Override
protected void firePropertyChange(String propertyName, Object oldValue,
Object newValue){
}

@Override
public void firePropertyChange(String propertyName, boolean oldValue,
boolean newValue){
}
}

if i create a JXTable and add this renderer, and then use
'JXTableSupport.install....' my custom renderer disappears.
If i use 'JXTableSupport.install...' and after that adding my renderer,
the layout looks like expected,
but the direction - arrows are away.

while debugging i saw, that i didn't come to '(icon != null)', also
before using 'JXTableSupport.install...'.

when adding some code to my renderer:

public Component getTableCellRendererComponent(JTable table, Object
value, boolean isSelected, boolean hasFocus, int row, int column){
...
setSortIcon(getIcon(table, column));
return this;
}

and this:



    /**
     * Overloaded to return an icon suitable to the primary sorted
column, or null if
     * the column is not the primary sort key.
     *
     * @param table the <code>JTable</code>.
     * @param column the column index.
     * @return the sort icon, or null if the column is unsorted.
     */
    protected Icon getIcon(JTable table, int column) {
        Icon icon = null;
        SortKey sortKey = getSortKey(table, column);
                if (sortKey != null &&
table.convertColumnIndexToView(sortKey.getColumn()) == column) {
                        switch (sortKey.getSortOrder()) {
                                case ASCENDING:
                            icon =
UIManager.getIcon("Table.ascendingSortIcon");
                                        break;
                                case DESCENDING:
                            icon =
UIManager.getIcon("Table.descendingSortIcon");
                                        break;
                                case UNSORTED:
                                        break;
                                default:
                                        break;
                        }
                }
                return icon;
    }

    /**
     * Returns the current sort key, or null if the column is unsorted.
     *
     * @param table the table
     * @param column the column index
     * @return the SortKey, or null if the column is unsorted
     */
    protected SortKey getSortKey(JTable table, int column) {
        RowSorter<?> rowSorter = table.getRowSorter();
        if (rowSorter == null) {
                return null;
        }

        List<?> sortedColumns = rowSorter.getSortKeys();
        if (sortedColumns.size() <= 0) {
                return null;
        } else {
                return (SortKey) sortedColumns.get(0);
        }
    }

and using this method before adding renderer:

table.setRowSorter(new
TableRowSorter<AdvancedTableModel<?>>(tableSupport.getTableModel()));
table.getTableHeader().setDefaultRenderer(new
PersonTableHeaderRenderer(0));

The arrow appears, but only on one column, equal whether the
sortingMode is Single_Column nor Multiple_Column.

is this a bug or a feature?

i mean, where is the error, i tried for 3 days now.

Can anyone help me?

(using latest glazedlists build, swingx-all-1.6.4 and jdk 8u45)
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Re: JXTableSupport

hbrands
Administrator
Hi Paul,

by using "JXTableSupport.install", JXTable is setup to work with Glazed Lists' sorting capabilities.
Among other things it calls "TableComparatorChooser.install" which wraps the current default TableHeader renderer
with an instance of ca.odell.glazedlists.swing.TableComparatorChooser$SortArrowHeaderRenderer.
The goal here is to provide and render the correct sorting icon for the table columns:
SortArrowHeaderRenderer determines in the method "getTableCellRendererComponent" the sorting icon for the column,
sets it into the wrapped header renderer (when it implements SortableRenderer) and then calls
"getTableCellRendererComponent" of the wrapped header renderer to render the cell value.

This usually works fine, but your header renderer is special in that it overwrites the paint-method for example.
So unfortunately, this renderer wrapping approach doesn't work in this case, because it only supports the TableCellRenderer interface contract.

I currently don't see an easy solution to your problem.

We could think about providing an alternative to the wrapping approach, where the header renderer is not replaced by a wrapper renderer,
but instead gets a "SortIconProvider" injected if the renderer implements another special interface.
Something like:

// custom header renderers would implement this interface
public interface SortIconRenderer {
void setSortIconProvider(SortIconProvider provider);
}

// Glazed Lists would provide and inject implementation of this interface into the SortIconRenderer
public interface SortIconProvider {
Icon getSortIcon(int column)
}

Then the custom header renderer implementation of method "getTableCellRendererComponent"
could call the injected SortIconProvider to get the sort icon for the current column and do what it wants to do.

WDYT?

Holger



2015-05-19 8:40 GMT+02:00 <[hidden email]>:
Hi,

i have a custom tableheaderrenderer looks like the following:

public class PersonTableHeaderRenderer extends JPanel
implements TableCellRenderer, SortableRenderer {

private static final long serialVersionUID = 0;

public static final int LEFT = 0;
public static final int RIGHT = 1;

public static final Color selectedTopStartColor =
ColorUtil.parseHtmlColor("#D0E0F4");
public static final Color selectedTopEndColor =
ColorUtil.parseHtmlColor("#8FBBE8");
public static final Color selectedBottomStartColor =
ColorUtil.parseHtmlColor("#6AAAEB");
public static final Color selectedBottomEndColor =
ColorUtil.parseHtmlColor("#B8FAFF");

public static final Color unselectedTopStartColor = Color.WHITE;
public static final Color unselectedTopEndColor =
ColorUtil.parseHtmlColor("#F2F2F2");
public static final Color unselectedBottomStartColor =
ColorUtil.parseHtmlColor("#E8E8E8");
public static final Color unselectedBottomEndColor = Color.WHITE;

public static final Color borderMiddleColor =
ColorUtil.parseHtmlColor("#666666");
public static final Color borderVerticalColor = new Color(150, 150,
150, 150);

protected JTable table;
protected Object value;
protected boolean isSelected;
protected boolean hasFocus;
protected int row;
protected int column;

private int justification = LEFT;
private final JLabel iconLabel = new JLabel();
private Image icon = null;


/**
* Konstruktor
*/
public PersonTableHeaderRenderer(){
super();
}

/**
* Konstruktor
* @param aJustification Ausrichtung
*/
public PersonTableHeaderRenderer(int aJustification){
super();
justification = aJustification;
iconLabel.setOpaque(false);
add(iconLabel, BorderLayout.EAST);
iconLabel.setVisible(true);
}

/**
* Setzt die Ausrichtung
* @param aJustification Ausrichtung
*/
public void setJustification(int aJustification){
justification = aJustification;
}

/**
* Gibt den Text von einem Object zurück
* @param aObject Object
* @return Text
*/
public String getText(Object aObject){
return aObject.toString();
}


/**
* Zeichnet die Bar neu
* erlaubt individuelle Designs
* @param g Grafik
*/
@Override
public void paint(Graphics g){
Graphics2D g2d = (Graphics2D) g;

Color topStartColor = isSelected ? selectedTopStartColor :
unselectedTopStartColor;
Color topEndColor = isSelected ? selectedTopEndColor :
unselectedTopEndColor;
Color bottomStartColor = isSelected ? selectedBottomStartColor :
unselectedBottomStartColor;
Color bottomEndColor = isSelected ? selectedBottomEndColor :
unselectedBottomEndColor;

Dimension vSize = getSize();

int h = vSize.height;
int w = vSize.width;

int h2 = h / 2;
int h4 = h / 4;

g2d.setPaint(new GradientPaint(0, 0, topStartColor, 0, h4,
topEndColor));
g2d.fillRect(0, 0, w, h2);

g2d.setColor(topEndColor);
g2d.setPaint(new GradientPaint(0, h4 + 1, topStartColor, 0, h2,
topEndColor));

g2d.setPaint(new GradientPaint(0, h2, bottomStartColor, 0, h - 2,
bottomEndColor));
g2d.fillRect(0, h2, w, h - 2);

g2d.setColor(borderMiddleColor);
g2d.drawLine(0, h - 1, w, h - 1);

boolean isLast = column == table.getColumnCount() - 1;
if (!isLast){
g2d.setColor(borderVerticalColor);
g2d.drawLine(w - 1, 0, w - 1, h - 1);
}

String vText = getText(value);
if (vText != null){
RenderingHints rh = new
RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHints(rh);
g2d.setFont(new Font("Arial", java.awt.Font.BOLD, 20));

Rectangle2D vRectangle =
g2d.getFontMetrics().getStringBounds(vText,g2d);
int sx;
if (justification == LEFT){
sx = 5;
} else {
sx = w-((int)vRectangle.getWidth()+5);
}
int sy = h - (h-(int)vRectangle.getHeight()) / 2 -
g2d.getFontMetrics().getDescent();

g2d.setColor(Color.BLACK);
g2d.drawString(vText, sx, sy);
}

//draw icon
if (icon != null){
//optimize quality
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
//draw it
int iconWidth = icon.getWidth(this);
int iconHeight = icon.getHeight(this);
g2d.drawImage(icon, w-iconWidth-2, (h-iconHeight)/2, iconWidth,
iconHeight, this);
} else {
System.out.println("no icon declared!");
}
}

/**
* Gibt die bevorzugte Größe zurück
* @return Bevorzugte Größe
*/
@Override
public Dimension getPreferredSize(){
Dimension vDimension = super.getPreferredSize();
vDimension.height = getFont().getSize() + 6;
return vDimension;
}

/**
* Gibt den Tabellenzellen Komponent zurück
* @param table Tabelle
* @param value Wert
* @param isSelected Ist selektiert? (true / false)
* @param hasFocus Ist fokussiert? (true / fale)
* @param row Zeile
* @param column Spalte
* @return Komponent
*/
@Override
public Component getTableCellRendererComponent(JTable table, Object
value, boolean isSelected, boolean hasFocus, int row, int column){
this.table = table;
this.value = value;
this.isSelected = isSelected;
this.hasFocus = hasFocus;
this.row = row;
this.column = column;

setFont(table.getFont());

return this;
}

/**
* Setzt das Sortierungs Icon
* @param sortIcon Icon
*/
@Override
public void setSortIcon(Icon sortIcon) {
if (sortIcon == null){
icon = null;
} else {
icon = ((ImageIcon)sortIcon).getImage();
}
}

//
-----------------------------------------------------------------------
-------------------------------------------
// The following methods override the defaults for performance reasons
//
-----------------------------------------------------------------------
-------------------------------------------
@Override
public void validate(){
}

@Override
public void revalidate(){
}

@Override
protected void firePropertyChange(String propertyName, Object oldValue,
Object newValue){
}

@Override
public void firePropertyChange(String propertyName, boolean oldValue,
boolean newValue){
}
}

if i create a JXTable and add this renderer, and then use
'JXTableSupport.install....' my custom renderer disappears.
If i use 'JXTableSupport.install...' and after that adding my renderer,
the layout looks like expected,
but the direction - arrows are away.

while debugging i saw, that i didn't come to '(icon != null)', also
before using 'JXTableSupport.install...'.

when adding some code to my renderer:

public Component getTableCellRendererComponent(JTable table, Object
value, boolean isSelected, boolean hasFocus, int row, int column){
...
setSortIcon(getIcon(table, column));
return this;
}

and this:



    /**
     * Overloaded to return an icon suitable to the primary sorted
column, or null if
     * the column is not the primary sort key.
     *
     * @param table the <code>JTable</code>.
     * @param column the column index.
     * @return the sort icon, or null if the column is unsorted.
     */
    protected Icon getIcon(JTable table, int column) {
        Icon icon = null;
        SortKey sortKey = getSortKey(table, column);
                if (sortKey != null &&
table.convertColumnIndexToView(sortKey.getColumn()) == column) {
                        switch (sortKey.getSortOrder()) {
                                case ASCENDING:
                            icon =
UIManager.getIcon("Table.ascendingSortIcon");
                                        break;
                                case DESCENDING:
                            icon =
UIManager.getIcon("Table.descendingSortIcon");
                                        break;
                                case UNSORTED:
                                        break;
                                default:
                                        break;
                        }
                }
                return icon;
    }

    /**
     * Returns the current sort key, or null if the column is unsorted.
     *
     * @param table the table
     * @param column the column index
     * @return the SortKey, or null if the column is unsorted
     */
    protected SortKey getSortKey(JTable table, int column) {
        RowSorter<?> rowSorter = table.getRowSorter();
        if (rowSorter == null) {
                return null;
        }

        List<?> sortedColumns = rowSorter.getSortKeys();
        if (sortedColumns.size() <= 0) {
                return null;
        } else {
                return (SortKey) sortedColumns.get(0);
        }
    }

and using this method before adding renderer:

table.setRowSorter(new
TableRowSorter<AdvancedTableModel<?>>(tableSupport.getTableModel()));
table.getTableHeader().setDefaultRenderer(new
PersonTableHeaderRenderer(0));

The arrow appears, but only on one column, equal whether the
sortingMode is Single_Column nor Multiple_Column.

is this a bug or a feature?

i mean, where is the error, i tried for 3 days now.

Can anyone help me?

(using latest glazedlists build, swingx-all-1.6.4 and jdk 8u45)

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Re: JXTableSupport

James Lemieux
We already define SortableRenderer for this purpose.

You should be able to do something like:

TableComparatorChooser tcc = TableComparatorChooser.install(...);
TableCellRenderer customHeaderRenderer = new MyAwesomeRenderer(); // MyAwesomeRenderer implements SortableRenderer
TableCellRenderer wrappedCustomHeaderRenderer = tcc.createSortArrowHeaderRenderer(customHeaderRenderer);
table.getTableHeader().getColumn(3).setHeaderRenderer( wrappedCustomHeaderRenderer); // change 3 to whatever column you're using


On Wed, May 20, 2015 at 1:44 PM, Holger Brands <[hidden email]> wrote:
Hi Paul,

by using "JXTableSupport.install", JXTable is setup to work with Glazed Lists' sorting capabilities.
Among other things it calls "TableComparatorChooser.install" which wraps the current default TableHeader renderer
with an instance of ca.odell.glazedlists.swing.TableComparatorChooser$SortArrowHeaderRenderer.
The goal here is to provide and render the correct sorting icon for the table columns:
SortArrowHeaderRenderer determines in the method "getTableCellRendererComponent" the sorting icon for the column,
sets it into the wrapped header renderer (when it implements SortableRenderer) and then calls
"getTableCellRendererComponent" of the wrapped header renderer to render the cell value.

This usually works fine, but your header renderer is special in that it overwrites the paint-method for example.
So unfortunately, this renderer wrapping approach doesn't work in this case, because it only supports the TableCellRenderer interface contract.

I currently don't see an easy solution to your problem.

We could think about providing an alternative to the wrapping approach, where the header renderer is not replaced by a wrapper renderer,
but instead gets a "SortIconProvider" injected if the renderer implements another special interface.
Something like:

// custom header renderers would implement this interface
public interface SortIconRenderer {
void setSortIconProvider(SortIconProvider provider);
}

// Glazed Lists would provide and inject implementation of this interface into the SortIconRenderer
public interface SortIconProvider {
Icon getSortIcon(int column)
}

Then the custom header renderer implementation of method "getTableCellRendererComponent"
could call the injected SortIconProvider to get the sort icon for the current column and do what it wants to do.

WDYT?

Holger



2015-05-19 8:40 GMT+02:00 <[hidden email]>:
Hi,

i have a custom tableheaderrenderer looks like the following:

public class PersonTableHeaderRenderer extends JPanel
implements TableCellRenderer, SortableRenderer {

private static final long serialVersionUID = 0;

public static final int LEFT = 0;
public static final int RIGHT = 1;

public static final Color selectedTopStartColor =
ColorUtil.parseHtmlColor("#D0E0F4");
public static final Color selectedTopEndColor =
ColorUtil.parseHtmlColor("#8FBBE8");
public static final Color selectedBottomStartColor =
ColorUtil.parseHtmlColor("#6AAAEB");
public static final Color selectedBottomEndColor =
ColorUtil.parseHtmlColor("#B8FAFF");

public static final Color unselectedTopStartColor = Color.WHITE;
public static final Color unselectedTopEndColor =
ColorUtil.parseHtmlColor("#F2F2F2");
public static final Color unselectedBottomStartColor =
ColorUtil.parseHtmlColor("#E8E8E8");
public static final Color unselectedBottomEndColor = Color.WHITE;

public static final Color borderMiddleColor =
ColorUtil.parseHtmlColor("#666666");
public static final Color borderVerticalColor = new Color(150, 150,
150, 150);

protected JTable table;
protected Object value;
protected boolean isSelected;
protected boolean hasFocus;
protected int row;
protected int column;

private int justification = LEFT;
private final JLabel iconLabel = new JLabel();
private Image icon = null;


/**
* Konstruktor
*/
public PersonTableHeaderRenderer(){
super();
}

/**
* Konstruktor
* @param aJustification Ausrichtung
*/
public PersonTableHeaderRenderer(int aJustification){
super();
justification = aJustification;
iconLabel.setOpaque(false);
add(iconLabel, BorderLayout.EAST);
iconLabel.setVisible(true);
}

/**
* Setzt die Ausrichtung
* @param aJustification Ausrichtung
*/
public void setJustification(int aJustification){
justification = aJustification;
}

/**
* Gibt den Text von einem Object zurück
* @param aObject Object
* @return Text
*/
public String getText(Object aObject){
return aObject.toString();
}


/**
* Zeichnet die Bar neu
* erlaubt individuelle Designs
* @param g Grafik
*/
@Override
public void paint(Graphics g){
Graphics2D g2d = (Graphics2D) g;

Color topStartColor = isSelected ? selectedTopStartColor :
unselectedTopStartColor;
Color topEndColor = isSelected ? selectedTopEndColor :
unselectedTopEndColor;
Color bottomStartColor = isSelected ? selectedBottomStartColor :
unselectedBottomStartColor;
Color bottomEndColor = isSelected ? selectedBottomEndColor :
unselectedBottomEndColor;

Dimension vSize = getSize();

int h = vSize.height;
int w = vSize.width;

int h2 = h / 2;
int h4 = h / 4;

g2d.setPaint(new GradientPaint(0, 0, topStartColor, 0, h4,
topEndColor));
g2d.fillRect(0, 0, w, h2);

g2d.setColor(topEndColor);
g2d.setPaint(new GradientPaint(0, h4 + 1, topStartColor, 0, h2,
topEndColor));

g2d.setPaint(new GradientPaint(0, h2, bottomStartColor, 0, h - 2,
bottomEndColor));
g2d.fillRect(0, h2, w, h - 2);

g2d.setColor(borderMiddleColor);
g2d.drawLine(0, h - 1, w, h - 1);

boolean isLast = column == table.getColumnCount() - 1;
if (!isLast){
g2d.setColor(borderVerticalColor);
g2d.drawLine(w - 1, 0, w - 1, h - 1);
}

String vText = getText(value);
if (vText != null){
RenderingHints rh = new
RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHints(rh);
g2d.setFont(new Font("Arial", java.awt.Font.BOLD, 20));

Rectangle2D vRectangle =
g2d.getFontMetrics().getStringBounds(vText,g2d);
int sx;
if (justification == LEFT){
sx = 5;
} else {
sx = w-((int)vRectangle.getWidth()+5);
}
int sy = h - (h-(int)vRectangle.getHeight()) / 2 -
g2d.getFontMetrics().getDescent();

g2d.setColor(Color.BLACK);
g2d.drawString(vText, sx, sy);
}

//draw icon
if (icon != null){
//optimize quality
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
//draw it
int iconWidth = icon.getWidth(this);
int iconHeight = icon.getHeight(this);
g2d.drawImage(icon, w-iconWidth-2, (h-iconHeight)/2, iconWidth,
iconHeight, this);
} else {
System.out.println("no icon declared!");
}
}

/**
* Gibt die bevorzugte Größe zurück
* @return Bevorzugte Größe
*/
@Override
public Dimension getPreferredSize(){
Dimension vDimension = super.getPreferredSize();
vDimension.height = getFont().getSize() + 6;
return vDimension;
}

/**
* Gibt den Tabellenzellen Komponent zurück
* @param table Tabelle
* @param value Wert
* @param isSelected Ist selektiert? (true / false)
* @param hasFocus Ist fokussiert? (true / fale)
* @param row Zeile
* @param column Spalte
* @return Komponent
*/
@Override
public Component getTableCellRendererComponent(JTable table, Object
value, boolean isSelected, boolean hasFocus, int row, int column){
this.table = table;
this.value = value;
this.isSelected = isSelected;
this.hasFocus = hasFocus;
this.row = row;
this.column = column;

setFont(table.getFont());

return this;
}

/**
* Setzt das Sortierungs Icon
* @param sortIcon Icon
*/
@Override
public void setSortIcon(Icon sortIcon) {
if (sortIcon == null){
icon = null;
} else {
icon = ((ImageIcon)sortIcon).getImage();
}
}

//
-----------------------------------------------------------------------
-------------------------------------------
// The following methods override the defaults for performance reasons
//
-----------------------------------------------------------------------
-------------------------------------------
@Override
public void validate(){
}

@Override
public void revalidate(){
}

@Override
protected void firePropertyChange(String propertyName, Object oldValue,
Object newValue){
}

@Override
public void firePropertyChange(String propertyName, boolean oldValue,
boolean newValue){
}
}

if i create a JXTable and add this renderer, and then use
'JXTableSupport.install....' my custom renderer disappears.
If i use 'JXTableSupport.install...' and after that adding my renderer,
the layout looks like expected,
but the direction - arrows are away.

while debugging i saw, that i didn't come to '(icon != null)', also
before using 'JXTableSupport.install...'.

when adding some code to my renderer:

public Component getTableCellRendererComponent(JTable table, Object
value, boolean isSelected, boolean hasFocus, int row, int column){
...
setSortIcon(getIcon(table, column));
return this;
}

and this:



    /**
     * Overloaded to return an icon suitable to the primary sorted
column, or null if
     * the column is not the primary sort key.
     *
     * @param table the <code>JTable</code>.
     * @param column the column index.
     * @return the sort icon, or null if the column is unsorted.
     */
    protected Icon getIcon(JTable table, int column) {
        Icon icon = null;
        SortKey sortKey = getSortKey(table, column);
                if (sortKey != null &&
table.convertColumnIndexToView(sortKey.getColumn()) == column) {
                        switch (sortKey.getSortOrder()) {
                                case ASCENDING:
                            icon =
UIManager.getIcon("Table.ascendingSortIcon");
                                        break;
                                case DESCENDING:
                            icon =
UIManager.getIcon("Table.descendingSortIcon");
                                        break;
                                case UNSORTED:
                                        break;
                                default:
                                        break;
                        }
                }
                return icon;
    }

    /**
     * Returns the current sort key, or null if the column is unsorted.
     *
     * @param table the table
     * @param column the column index
     * @return the SortKey, or null if the column is unsorted
     */
    protected SortKey getSortKey(JTable table, int column) {
        RowSorter<?> rowSorter = table.getRowSorter();
        if (rowSorter == null) {
                return null;
        }

        List<?> sortedColumns = rowSorter.getSortKeys();
        if (sortedColumns.size() <= 0) {
                return null;
        } else {
                return (SortKey) sortedColumns.get(0);
        }
    }

and using this method before adding renderer:

table.setRowSorter(new
TableRowSorter<AdvancedTableModel<?>>(tableSupport.getTableModel()));
table.getTableHeader().setDefaultRenderer(new
PersonTableHeaderRenderer(0));

The arrow appears, but only on one column, equal whether the
sortingMode is Single_Column nor Multiple_Column.

is this a bug or a feature?

i mean, where is the error, i tried for 3 days now.

Can anyone help me?

(using latest glazedlists build, swingx-all-1.6.4 and jdk 8u45)


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Re: JXTableSupport

hbrands
Administrator
My assumption was that the renderer wrapping approach of TableComparatorChooser was the problem, but I was wrong.
I think James suggestion should work as a workaround. Paul, can you confirm that?
(If using JXTableSupport.install you can get at the TableComparatorChooser via JXTableSupport.getTableComparatorChooser())


I think the real cause of the problem is, that using JXTableSupport.install will replace the
default table header renderer with the result of JTableHeader().getDefaultRenderer().
I was not aware of this until I debugged it now.
I think we should fix this by don't replacing the default table header renderer in JXTableSupport.install like that anymore.
For example, a renderer which implements SortableRenderer seems perfectly valid to me.

I will also remove SwingX 1.0 support as we are moving to Java 1.6 (and SwingX 1.6.x) as baseline.

Holger


2015-05-20 23:13 GMT+02:00 James Lemieux <[hidden email]>:
We already define SortableRenderer for this purpose.

You should be able to do something like:

TableComparatorChooser tcc = TableComparatorChooser.install(...);
TableCellRenderer customHeaderRenderer = new MyAwesomeRenderer(); // MyAwesomeRenderer implements SortableRenderer
TableCellRenderer wrappedCustomHeaderRenderer = tcc.createSortArrowHeaderRenderer(customHeaderRenderer);
table.getTableHeader().getColumn(3).setHeaderRenderer( wrappedCustomHeaderRenderer); // change 3 to whatever column you're using


On Wed, May 20, 2015 at 1:44 PM, Holger Brands <[hidden email]> wrote:
Hi Paul,

by using "JXTableSupport.install", JXTable is setup to work with Glazed Lists' sorting capabilities.
Among other things it calls "TableComparatorChooser.install" which wraps the current default TableHeader renderer
with an instance of ca.odell.glazedlists.swing.TableComparatorChooser$SortArrowHeaderRenderer.
The goal here is to provide and render the correct sorting icon for the table columns:
SortArrowHeaderRenderer determines in the method "getTableCellRendererComponent" the sorting icon for the column,
sets it into the wrapped header renderer (when it implements SortableRenderer) and then calls
"getTableCellRendererComponent" of the wrapped header renderer to render the cell value.

This usually works fine, but your header renderer is special in that it overwrites the paint-method for example.
So unfortunately, this renderer wrapping approach doesn't work in this case, because it only supports the TableCellRenderer interface contract.

I currently don't see an easy solution to your problem.

We could think about providing an alternative to the wrapping approach, where the header renderer is not replaced by a wrapper renderer,
but instead gets a "SortIconProvider" injected if the renderer implements another special interface.
Something like:

// custom header renderers would implement this interface
public interface SortIconRenderer {
void setSortIconProvider(SortIconProvider provider);
}

// Glazed Lists would provide and inject implementation of this interface into the SortIconRenderer
public interface SortIconProvider {
Icon getSortIcon(int column)
}

Then the custom header renderer implementation of method "getTableCellRendererComponent"
could call the injected SortIconProvider to get the sort icon for the current column and do what it wants to do.

WDYT?

Holger



2015-05-19 8:40 GMT+02:00 <[hidden email]>:
Hi,

i have a custom tableheaderrenderer looks like the following:

public class PersonTableHeaderRenderer extends JPanel
implements TableCellRenderer, SortableRenderer {

private static final long serialVersionUID = 0;

public static final int LEFT = 0;
public static final int RIGHT = 1;

public static final Color selectedTopStartColor =
ColorUtil.parseHtmlColor("#D0E0F4");
public static final Color selectedTopEndColor =
ColorUtil.parseHtmlColor("#8FBBE8");
public static final Color selectedBottomStartColor =
ColorUtil.parseHtmlColor("#6AAAEB");
public static final Color selectedBottomEndColor =
ColorUtil.parseHtmlColor("#B8FAFF");

public static final Color unselectedTopStartColor = Color.WHITE;
public static final Color unselectedTopEndColor =
ColorUtil.parseHtmlColor("#F2F2F2");
public static final Color unselectedBottomStartColor =
ColorUtil.parseHtmlColor("#E8E8E8");
public static final Color unselectedBottomEndColor = Color.WHITE;

public static final Color borderMiddleColor =
ColorUtil.parseHtmlColor("#666666");
public static final Color borderVerticalColor = new Color(150, 150,
150, 150);

protected JTable table;
protected Object value;
protected boolean isSelected;
protected boolean hasFocus;
protected int row;
protected int column;

private int justification = LEFT;
private final JLabel iconLabel = new JLabel();
private Image icon = null;


/**
* Konstruktor
*/
public PersonTableHeaderRenderer(){
super();
}

/**
* Konstruktor
* @param aJustification Ausrichtung
*/
public PersonTableHeaderRenderer(int aJustification){
super();
justification = aJustification;
iconLabel.setOpaque(false);
add(iconLabel, BorderLayout.EAST);
iconLabel.setVisible(true);
}

/**
* Setzt die Ausrichtung
* @param aJustification Ausrichtung
*/
public void setJustification(int aJustification){
justification = aJustification;
}

/**
* Gibt den Text von einem Object zurück
* @param aObject Object
* @return Text
*/
public String getText(Object aObject){
return aObject.toString();
}


/**
* Zeichnet die Bar neu
* erlaubt individuelle Designs
* @param g Grafik
*/
@Override
public void paint(Graphics g){
Graphics2D g2d = (Graphics2D) g;

Color topStartColor = isSelected ? selectedTopStartColor :
unselectedTopStartColor;
Color topEndColor = isSelected ? selectedTopEndColor :
unselectedTopEndColor;
Color bottomStartColor = isSelected ? selectedBottomStartColor :
unselectedBottomStartColor;
Color bottomEndColor = isSelected ? selectedBottomEndColor :
unselectedBottomEndColor;

Dimension vSize = getSize();

int h = vSize.height;
int w = vSize.width;

int h2 = h / 2;
int h4 = h / 4;

g2d.setPaint(new GradientPaint(0, 0, topStartColor, 0, h4,
topEndColor));
g2d.fillRect(0, 0, w, h2);

g2d.setColor(topEndColor);
g2d.setPaint(new GradientPaint(0, h4 + 1, topStartColor, 0, h2,
topEndColor));

g2d.setPaint(new GradientPaint(0, h2, bottomStartColor, 0, h - 2,
bottomEndColor));
g2d.fillRect(0, h2, w, h - 2);

g2d.setColor(borderMiddleColor);
g2d.drawLine(0, h - 1, w, h - 1);

boolean isLast = column == table.getColumnCount() - 1;
if (!isLast){
g2d.setColor(borderVerticalColor);
g2d.drawLine(w - 1, 0, w - 1, h - 1);
}

String vText = getText(value);
if (vText != null){
RenderingHints rh = new
RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHints(rh);
g2d.setFont(new Font("Arial", java.awt.Font.BOLD, 20));

Rectangle2D vRectangle =
g2d.getFontMetrics().getStringBounds(vText,g2d);
int sx;
if (justification == LEFT){
sx = 5;
} else {
sx = w-((int)vRectangle.getWidth()+5);
}
int sy = h - (h-(int)vRectangle.getHeight()) / 2 -
g2d.getFontMetrics().getDescent();

g2d.setColor(Color.BLACK);
g2d.drawString(vText, sx, sy);
}

//draw icon
if (icon != null){
//optimize quality
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
//draw it
int iconWidth = icon.getWidth(this);
int iconHeight = icon.getHeight(this);
g2d.drawImage(icon, w-iconWidth-2, (h-iconHeight)/2, iconWidth,
iconHeight, this);
} else {
System.out.println("no icon declared!");
}
}

/**
* Gibt die bevorzugte Größe zurück
* @return Bevorzugte Größe
*/
@Override
public Dimension getPreferredSize(){
Dimension vDimension = super.getPreferredSize();
vDimension.height = getFont().getSize() + 6;
return vDimension;
}

/**
* Gibt den Tabellenzellen Komponent zurück
* @param table Tabelle
* @param value Wert
* @param isSelected Ist selektiert? (true / false)
* @param hasFocus Ist fokussiert? (true / fale)
* @param row Zeile
* @param column Spalte
* @return Komponent
*/
@Override
public Component getTableCellRendererComponent(JTable table, Object
value, boolean isSelected, boolean hasFocus, int row, int column){
this.table = table;
this.value = value;
this.isSelected = isSelected;
this.hasFocus = hasFocus;
this.row = row;
this.column = column;

setFont(table.getFont());

return this;
}

/**
* Setzt das Sortierungs Icon
* @param sortIcon Icon
*/
@Override
public void setSortIcon(Icon sortIcon) {
if (sortIcon == null){
icon = null;
} else {
icon = ((ImageIcon)sortIcon).getImage();
}
}

//
-----------------------------------------------------------------------
-------------------------------------------
// The following methods override the defaults for performance reasons
//
-----------------------------------------------------------------------
-------------------------------------------
@Override
public void validate(){
}

@Override
public void revalidate(){
}

@Override
protected void firePropertyChange(String propertyName, Object oldValue,
Object newValue){
}

@Override
public void firePropertyChange(String propertyName, boolean oldValue,
boolean newValue){
}
}

if i create a JXTable and add this renderer, and then use
'JXTableSupport.install....' my custom renderer disappears.
If i use 'JXTableSupport.install...' and after that adding my renderer,
the layout looks like expected,
but the direction - arrows are away.

while debugging i saw, that i didn't come to '(icon != null)', also
before using 'JXTableSupport.install...'.

when adding some code to my renderer:

public Component getTableCellRendererComponent(JTable table, Object
value, boolean isSelected, boolean hasFocus, int row, int column){
...
setSortIcon(getIcon(table, column));
return this;
}

and this:



    /**
     * Overloaded to return an icon suitable to the primary sorted
column, or null if
     * the column is not the primary sort key.
     *
     * @param table the <code>JTable</code>.
     * @param column the column index.
     * @return the sort icon, or null if the column is unsorted.
     */
    protected Icon getIcon(JTable table, int column) {
        Icon icon = null;
        SortKey sortKey = getSortKey(table, column);
                if (sortKey != null &&
table.convertColumnIndexToView(sortKey.getColumn()) == column) {
                        switch (sortKey.getSortOrder()) {
                                case ASCENDING:
                            icon =
UIManager.getIcon("Table.ascendingSortIcon");
                                        break;
                                case DESCENDING:
                            icon =
UIManager.getIcon("Table.descendingSortIcon");
                                        break;
                                case UNSORTED:
                                        break;
                                default:
                                        break;
                        }
                }
                return icon;
    }

    /**
     * Returns the current sort key, or null if the column is unsorted.
     *
     * @param table the table
     * @param column the column index
     * @return the SortKey, or null if the column is unsorted
     */
    protected SortKey getSortKey(JTable table, int column) {
        RowSorter<?> rowSorter = table.getRowSorter();
        if (rowSorter == null) {
                return null;
        }

        List<?> sortedColumns = rowSorter.getSortKeys();
        if (sortedColumns.size() <= 0) {
                return null;
        } else {
                return (SortKey) sortedColumns.get(0);
        }
    }

and using this method before adding renderer:

table.setRowSorter(new
TableRowSorter<AdvancedTableModel<?>>(tableSupport.getTableModel()));
table.getTableHeader().setDefaultRenderer(new
PersonTableHeaderRenderer(0));

The arrow appears, but only on one column, equal whether the
sortingMode is Single_Column nor Multiple_Column.

is this a bug or a feature?

i mean, where is the error, i tried for 3 days now.

Can anyone help me?

(using latest glazedlists build, swingx-all-1.6.4 and jdk 8u45)



Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Re: Re: JXTableSupport

PaulPaulsson
In reply to this post by PaulPaulsson
Hi guys,

sry was on a little vacation for the holidays, u know holger.

I've checked what u both say.

so i changed my code like this:

public class PersonTableHeaderRenderer extends JPanel
implements TableCellRenderer, SortableRenderer {}


without the methods:

setSortIcon(getIcon(table, column)); in
getTableCellRendererComponent(...

and

/**
 * Overloaded to return an icon suitable to the primary sorted column,
or null if
 * the column is not the primary sort key.
 *
 * @param table the <code>JTable</code>.
 * @param column the column index.
 * @return the sort icon, or null if the column is unsorted.
 */
protected Icon getIcon(JTable table, int column) {
    Icon icon = null;
    SortKey sortKey = getSortKey(table, column);
    if (sortKey != null &&
table.convertColumnIndexToView(sortKey.getColumn()) == column) {
        switch (sortKey.getSortOrder()) {
        case ASCENDING:
            icon = UIManager.getIcon("Table.ascendingSortIcon");
            break;
        case DESCENDING:
            icon = UIManager.getIcon("Table.descendingSortIcon");
            break;
        case UNSORTED:
            break;
        default:
            break;
        }
    }
    return icon;
}

/**
 * Returns the current sort key, or null if the column is unsorted.
 *
 * @param table the table
 * @param column the column index
 * @return the SortKey, or null if the column is unsorted
 */
protected SortKey getSortKey(JTable table, int column) {
    RowSorter<?> rowSorter = table.getRowSorter();
    if (rowSorter == null) {
        return null;
    }

    List<?> sortedColumns = rowSorter.getSortKeys();
    if (sortedColumns.size() <= 0) {
        return null;
    } else {
        return (SortKey) sortedColumns.get(0);
    }
}

And then changing my GLTableBuilder - Class to this:

//create table with new JXTableSupport
TableComparatorChooser.setIconPath("resources/aqua");
JXTableSupport<E> jxTableSupport = JXTableSupport.<E>install(table,
sortedList, tableFormat, sortedList, sortingMode);

tableComparatorChooser = jxTableSupport.getTableComparatorChooser();
TableCellRenderer pthRenderer =
tableComparatorChooser.createSortArrowHeaderRenderer(new
PersonTableHeaderRenderer(0));
table.getTableHeader().setDefaultRenderer(pthRenderer);

And my layout appears including the arrows.

Thanks for helping!

Best regards
Paul
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Re: Re: JXTableSupport

hbrands
Administrator
Hi Paul,

even better, the latest 1.10 snapshot of Glazed Lists has a fix for GLAZEDLISTS-580.
So now something like this should work as long as your custom renderer implements SortableRenderer:
        ...
        JXTable t = new JXTable();
        t.getTableHeader().setDefaultRenderer(new PersonTableHeaderRenderer());
        TableFormat<Person> tableFormat = GlazedLists.<Person> tableFormat(
                propertyNames, columnLabels, writable);
        JXTableSupport<Person> tableSupport = JXTableSupport.<Person> install(
                t, sortedList, tableFormat, sortedList, sortingMode);
        ...

Holger


2015-05-26 8:38 GMT+02:00 <[hidden email]>:
Hi guys,

sry was on a little vacation for the holidays, u know holger.

I've checked what u both say.

so i changed my code like this:

public class PersonTableHeaderRenderer extends JPanel
implements TableCellRenderer, SortableRenderer {}


without the methods:

setSortIcon(getIcon(table, column)); in
getTableCellRendererComponent(...

and

/**
 * Overloaded to return an icon suitable to the primary sorted column,
or null if
 * the column is not the primary sort key.
 *
 * @param table the <code>JTable</code>.
 * @param column the column index.
 * @return the sort icon, or null if the column is unsorted.
 */
protected Icon getIcon(JTable table, int column) {
    Icon icon = null;
    SortKey sortKey = getSortKey(table, column);
    if (sortKey != null &&
table.convertColumnIndexToView(sortKey.getColumn()) == column) {
        switch (sortKey.getSortOrder()) {
        case ASCENDING:
            icon = UIManager.getIcon("Table.ascendingSortIcon");
            break;
        case DESCENDING:
            icon = UIManager.getIcon("Table.descendingSortIcon");
            break;
        case UNSORTED:
            break;
        default:
            break;
        }
    }
    return icon;
}

/**
 * Returns the current sort key, or null if the column is unsorted.
 *
 * @param table the table
 * @param column the column index
 * @return the SortKey, or null if the column is unsorted
 */
protected SortKey getSortKey(JTable table, int column) {
    RowSorter<?> rowSorter = table.getRowSorter();
    if (rowSorter == null) {
        return null;
    }

    List<?> sortedColumns = rowSorter.getSortKeys();
    if (sortedColumns.size() <= 0) {
        return null;
    } else {
        return (SortKey) sortedColumns.get(0);
    }
}

And then changing my GLTableBuilder - Class to this:

//create table with new JXTableSupport
TableComparatorChooser.setIconPath("resources/aqua");
JXTableSupport<E> jxTableSupport = JXTableSupport.<E>install(table,
sortedList, tableFormat, sortedList, sortingMode);

tableComparatorChooser = jxTableSupport.getTableComparatorChooser();
TableCellRenderer pthRenderer =
tableComparatorChooser.createSortArrowHeaderRenderer(new
PersonTableHeaderRenderer(0));
table.getTableHeader().setDefaultRenderer(pthRenderer);

And my layout appears including the arrows.

Thanks for helping!

Best regards
Paul

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Re: Re: Re: JXTableSupport

PaulPaulsson
In reply to this post by PaulPaulsson
Hi, this works like expected,

without using the workaround from james.

I create my JXTable with my customtabelheaderrenderer implementing
sortablerenderer, without using this line of code:

table.getTableHeader().setDefaultRenderer(tableComparatorChooser.create
SortArrowHeaderRenderer(new PersonTableHeaderRenderer(0)));

and it works well with the new Snapshot from 30th May.

Thanks guys.


Greetz Paul
Loading...