Markieren von ganzen Zeilen in transparenten Tabellen

mrsmola

Mitglied
Hallo zusammen,

ich habe zur Zeit folgendes Problem:

Ich habe mir in einer Anwendung eine Tabelle aufgebaut, in der die Zellen und Header transparent gestaltet sind. Über einen CellRenderer und einen HeaderRenderer lege ich per setIcon zusätzlich Grafiken sowohl in die Header als auch in die einzelnen Zellen. Diese Grafiken sind ebenfalls zu 60% transparent.

Jetzt ist in der Anwendung der Bedarf aufgekommen einzelne Zeilen anklicken zu können. Da ich aufgrund der Grafiken in den Zellen nicht mit Hintergrundfarben arbeiten kann möchte ich beim Klick auf eine Zelle in allen Zellen der Zeile die Hintergrundgrafiken austauschen. Eine eventuell vorher Markierte Zeile soll wieder die Ursprungsgrafiken bekommen.

Folgender Beispielcode entspricht ungefähr dem Code in der Anwendung. Die Benutzung der Grafiken habe ich auskommentiert.

Kann mir jemand sagen wie das bewerkstelligen kann? Im CellRenderer bekomme ich mit ob eine Zelle selektiert wurde und ob sie den Fokus hat. Die Zeile kenne ich und die Anzahl der Spalten kann ich mir auch holen. Beim Rest der Problemlösung stehe ich auf dem Schlauch.

Java:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.List;
 
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SortOrder;
import javax.swing.RowSorter.SortKey;
import javax.swing.border.BevelBorder;
import javax.swing.border.LineBorder;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
 
public class TableDemo extends JFrame
{
    
    private TableRowSorter<TableModel> rowSorter = null;
    private JScrollPane scrollPane = null;
    
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TableDemo().setVisible(true);
            }
        });
    }
    
    public TableDemo()
    {
        super("TableDemo");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        
        getContentPane().add( getScrollPaneSpieler() );
        pack();
    }
    
    private JScrollPane getScrollPaneSpieler()
    {
        if (scrollPane == null)
        {
            scrollPane = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_NEVER,
                                                      JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            scrollPane.setOpaque(false);
            scrollPane.setBounds(new Rectangle(10, 130, 500, 300));
            scrollPane.setViewportView(getTable());
            scrollPane.getViewport().setOpaque(false); 
            scrollPane.getVerticalScrollBar().setOpaque(false);
            scrollPane.setBorder(new BevelBorder(BevelBorder.RAISED));
            scrollPane.setVisible(true);
        }   
        return scrollPane;
    }
    
    public JTable getTable()
    {
        JTable table = null;
        
        Object[][] data = new Object[][]{
                {1, 5, 8, 9, 0},
                {2, 4, 7, 7, 5},
                {3, 3, 6, 8, 6},
                {7, 5, 8, 7, 7},
                {8, 1, 1, 1, 8},
                {8, 1, 9, 3, 1},
                {8, 2, 9, 3, 4},
                {8, 8, 2, 1, 8},
                {7, 5, 8, 9, 5}
        };
        
        String[] columnNames = new String[]{
                "Spalte A", "Spalte B", "Spalte C", "Spalte D", "Spalte E"
        };
        
        table = new JTable( data, columnNames );
        table.setLayout(new BoxLayout(table, BoxLayout.Y_AXIS));
        table.setOpaque(false);
        table.setPreferredSize(new Dimension(400,250));
        table.getTableHeader().setOpaque(false);
        table.setBorder(new LineBorder(Color.gray));
        
        table.setAutoCreateRowSorter(true);
        rowSorter = new TableRowSorter<TableModel>(table.getModel());
        rowSorter.setMaxSortKeys(2);
        table.setRowSorter(rowSorter);
       
        TableColumn tableColumnA = table.getColumn("Spalte A");
        tableColumnA.setResizable(false);
        tableColumnA.setCellRenderer(new CellRenderer());
        tableColumnA.setHeaderRenderer(new HeaderRenderer(table));
        
        TableColumn tableColumnB = table.getColumn("Spalte B");
        tableColumnB.setResizable(false);
        tableColumnB.setCellRenderer(new CellRenderer());
        tableColumnB.setHeaderRenderer(new HeaderRenderer(table));
        
        TableColumn tableColumnC = table.getColumn("Spalte C");
        tableColumnC.setResizable(false);
        tableColumnC.setCellRenderer(new CellRenderer());
        tableColumnC.setHeaderRenderer(new HeaderRenderer(table));
        
        TableColumn tableColumnD = table.getColumn("Spalte D");
        tableColumnD.setResizable(false);
        tableColumnD.setCellRenderer(new CellRenderer());
        tableColumnD.setHeaderRenderer(new HeaderRenderer(table));
        
        TableColumn tableColumnE = table.getColumn("Spalte E");
        tableColumnE.setResizable(false);
        tableColumnE.setCellRenderer(new CellRenderer());
        tableColumnE.setHeaderRenderer(new HeaderRenderer(table));
        
        return table;
    }
    
    public class CellRenderer extends DefaultTableCellRenderer implements TableCellRenderer {
        
        public CellRenderer()
        {
            this.setHorizontalAlignment(JLabel.LEFT);
            this.setForeground(Color.black);
            this.setFont(new Font("Helvetica", Font.PLAIN,12));
            this.setOpaque(false);
        }
        
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col)
        {
            this.setText(value.toString());
            this.setSize(table.getCellRect(row, col, true).width, 16);
         
          /*
         // Hintergrund verändern aufgrund der Position
        	if (row%2==0)
        		this.setIcon(Konstanten.TABLE_BACKGROUND_GERADE_ZELLEN);
            else
            	this.setIcon(Konstanten.TABLE_BACKGROUND_UNGERADE_ZELLEN);
          */  
            return this;
        }
    }
    
    public class HeaderRenderer extends DefaultTableCellRenderer implements TableCellRenderer {
 
        private Icon mAscending = new AscendingIcon();
        private Icon mDescending = new DescendingIcon();
        private Icon mNull = new NullIcon();
       
        List<? extends SortKey> skeys = null;
        
        public HeaderRenderer(JTable table)
        {
            this.setHorizontalAlignment(JLabel.LEFT);
            this.setForeground(Color.blue);
            this.setFont(new Font("Helvetica", Font.BOLD,12));
            this.setOpaque(false);
            this.setHorizontalAlignment(JLabel.CENTER);
        }
        
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col)
        {
            this.setText(value.toString());
            
            //this.setIcon(Konstanten.TABLE_BACKGROUND_HEADER);
            
            skeys = table.getRowSorter().getSortKeys();
            if (skeys != null)
            {
                
                for (SortKey sortKey : skeys)
                {
                    int columnIndex = table.convertColumnIndexToView(sortKey.getColumn());
 
                     if (col == columnIndex)
                    {
                        if(sortKey.getSortOrder() == SortOrder.ASCENDING)
                        {
                            setIcon(mAscending);
                            return this;
                        }
                        else if (sortKey.getSortOrder() == SortOrder.DESCENDING)
                        {
                            setIcon(mDescending);
                            return this;
                        }
                    }
                }
            }
            setIcon(mNull);
            return this;
        }
    }
    
    public class NullIcon implements Icon
    {
        public int getIconHeight()
        {
            return 6;
        }
 
        public int getIconWidth()
        {
            return 6;
        }
 
        public void paintIcon(Component pComponent, Graphics pGraphics, int pX, int pY)
        {
        }
    }
    
    public class AscendingIcon extends NullIcon
    {
        public void paintIcon(Component pComponent, Graphics pGraphics, int pX, int pY)
        {
            int[] xx = {pX, pX + 3, pX + 6};
            int[] yy = {pY + 6, pY, pY + 6};
 
            Color initialColor = pGraphics.getColor();
            float[] initial = Color.RGBtoHSB(initialColor.getRed(), initialColor.getGreen(), initialColor.getBlue(), null);
            boolean need = initial[2] < .5f;
            initial[2] = invertAsNeed(initial[2], need);
 
            Color line = Color.getHSBColor(initial[0], initial[1], invertAsNeed(initial[2] * .7f, need));
            Color fill = Color.getHSBColor(initial[0], initial[1], invertAsNeed(initial[2] * .35f, need));
            pGraphics.setColor(fill);
            pGraphics.fillPolygon(xx, yy, 3);
            pGraphics.setColor(line);
            pGraphics.drawPolygon(xx, yy, 3);
        }
        
        private float invertAsNeed(float pBright, boolean pNeed)
        {
            return pNeed ? 1 - pBright : pBright;
        }
    }
    
    public class DescendingIcon extends NullIcon {
       public void paintIcon(Component pComponent, Graphics pGraphics, int pX,
                int pY) {
            int[] xx = {pX, pX + 3, pX + 6};
            int[] yy = {pY, pY + 6, pY + 0};
 
            Color initialColor = pGraphics.getColor();
            float[] initial = Color.RGBtoHSB(initialColor.getRed(),
                    initialColor.getGreen(), initialColor.getBlue(), null);
 
            boolean need = initial[2] < .5f;
            initial[2] = invertAsNeed(initial[2], need);
 
            Color line = Color.getHSBColor(initial[0], initial[1],
                    invertAsNeed(initial[2] * .7f, need));
            Color fill = Color.getHSBColor(initial[0], initial[1],
                    invertAsNeed(initial[2] * .35f, need));
            pGraphics.setColor(fill);
            pGraphics.fillPolygon(xx, yy, 3);
            pGraphics.setColor(line);
            pGraphics.drawPolygon(xx, yy, 3);
        }
        
        private float invertAsNeed(float pBright, boolean pNeed)
        {
            return pNeed ? 1 - pBright : pBright;
        }
    }
}
 
Verstehe ich hier etwas falsch? Du hast doch selbst gesagt, dass du im Renderer weißt, ob eine Zelle selektiert ist, oder nicht, entsprechend kannst du die Methode doch implementieren:
Java:
if (isSelected)
    setIcon( selectedIcon );
else
    setIcon( normalIcon );

Dies natürlich entsprechend einbetten. Das sollte genügen, denn sobald du die Selektion wechselst. Wird der Renderer automatisch für die beiden Zeilen (alte Selektion und neue) aufgerufen.

Wenn deine Tabelle 'nur' zu 60% transparent ist, kannst du aber dennoch den Hintergrund setzen. Ich weiß nicht wie intuitiv diese Selektion via Icons für einen Anwender ist.
 
In die aktuelle Zelle bekomme ich den Hintergrund gesetzt. Ich möchte jedoch der ganzen Zeile einen neuen Hintergrund bei einem Klick auf eine Zeller dieser Zeile geben. Die Zeile soll somit als Ganzes ausgewählt werden können.

In der Tabelle sind Personen mit Eigenschaften vorhanden. Eine Zeile steht immer für eine Person. Beim Klick auf eine Eigenschaft soll also die gesamte Person (Zeile) als markiert erscheinen.

Beim Einfärben des Hintergrundes hätte ich das gleiche Problem. Wie komme ich an die restlichen Zellen der Zeile ran. Einfärben geht in meinem Fall vermutlich nicht, weil ich die Tabelle in jedem Fall transparent halten möchte. Wenn ich es richtig im Kopf habe geht die Transparenz bei einer Einfärbung des Hintergrundes verloren, oder?
 
Ist denn der SelectionMode der Tabelle richtig gesetzt? Sprich via
Java:
myTable.getSelectionModel().setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
 // oder so ähnlich
 // und zusätzlich:
myTable.getColumnModel().setColumnSelectionAllowed( false );
 // oder so ähnlich ;)
Das sollte genügen.
 
Den SelectionMode hatte ich schon ausprobiert. Ein verändertes Verhalten konnte ich nicht feststellen.

Ich habe ihn in den Test-Code wieder eingebaut:

Java:
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setColumnSelectionAllowed(false);
table.setRowSelectionAllowed(true);
table.setCellSelectionEnabled(false);

Da im Test-Code keine Grafiken eingebaut sind habe ich die Rahmen der Zelle gesetzt. Die Rahmen kann ich ja später gegen die Hintergrundgrafiken austauschen:

Java:
if (hasFocus)
	this.setBorder(BorderFactory.createLineBorder(table.getForeground(), 1));
else
	this.setBorder(BorderFactory.createLineBorder(table.getForeground(), 0));

Beim Klick auf eine Zelle bekommt diese jetzt einen Rahmen. Den SelectionMode benötige ich dafür nicht.

Ich hatte gehofft, dass ich im CellRenderer jetzt die anderen Zellen der Zeile ebenfalls mit einem Rahmen beglücken kann. Die Zeile ist mir ja bekannt. Die Anzahl der Spalten kann ich mir über die Tabelle holen.

Hier ist nochmal der aktuelle Testcode mit Rahmen und SelectionMode.
Java:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.List;
 
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SortOrder;
import javax.swing.RowSorter.SortKey;
import javax.swing.border.BevelBorder;
import javax.swing.border.LineBorder;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
 
public class TableDemo extends JFrame
{
    
    private TableRowSorter<TableModel> rowSorter = null;
    private JScrollPane scrollPane = null;
    
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TableDemo().setVisible(true);
            }
        });
    }
    
    public TableDemo()
    {
        super("TableDemo");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        
        getContentPane().add( getScrollPaneSpieler() );
        pack();
    }
    
    private JScrollPane getScrollPaneSpieler()
    {
        if (scrollPane == null)
        {
            scrollPane = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_NEVER,
                                                      JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            scrollPane.setOpaque(false);
            scrollPane.setBounds(new Rectangle(10, 130, 500, 300));
            scrollPane.setViewportView(getTable());
            scrollPane.getViewport().setOpaque(false); 
            scrollPane.getVerticalScrollBar().setOpaque(false);
            scrollPane.setBorder(new BevelBorder(BevelBorder.RAISED));
            scrollPane.setVisible(true);
        }   
        return scrollPane;
    }
    
    public JTable getTable()
    {
        JTable table = null;
        
        Object[][] data = new Object[][]{
                {1, 5, 8, 9, 0},
                {2, 4, 7, 7, 5},
                {3, 3, 6, 8, 6},
                {7, 5, 8, 7, 7},
                {8, 1, 1, 1, 8},
                {8, 1, 9, 3, 1},
                {8, 2, 9, 3, 4},
                {8, 8, 2, 1, 8},
                {7, 5, 8, 9, 5}
        };
        
        String[] columnNames = new String[]{
                "Spalte A", "Spalte B", "Spalte C", "Spalte D", "Spalte E"
        };
        
        table = new JTable( data, columnNames );
        table.setLayout(new BoxLayout(table, BoxLayout.Y_AXIS));
        table.setOpaque(false);
        table.setPreferredSize(new Dimension(400,250));
        table.getTableHeader().setOpaque(false);
        table.setBorder(new LineBorder(Color.gray));
        
        table.setAutoCreateRowSorter(true);
        rowSorter = new TableRowSorter<TableModel>(table.getModel());
        rowSorter.setMaxSortKeys(2);
        table.setRowSorter(rowSorter);
        
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		table.setColumnSelectionAllowed(false);
		table.setRowSelectionAllowed(true);
		table.setCellSelectionEnabled(false);
       
        TableColumn tableColumnA = table.getColumn("Spalte A");
        tableColumnA.setResizable(false);
        tableColumnA.setCellRenderer(new CellRenderer());
        tableColumnA.setHeaderRenderer(new HeaderRenderer(table));
        
        TableColumn tableColumnB = table.getColumn("Spalte B");
        tableColumnB.setResizable(false);
        tableColumnB.setCellRenderer(new CellRenderer());
        tableColumnB.setHeaderRenderer(new HeaderRenderer(table));
        
        TableColumn tableColumnC = table.getColumn("Spalte C");
        tableColumnC.setResizable(false);
        tableColumnC.setCellRenderer(new CellRenderer());
        tableColumnC.setHeaderRenderer(new HeaderRenderer(table));
        
        TableColumn tableColumnD = table.getColumn("Spalte D");
        tableColumnD.setResizable(false);
        tableColumnD.setCellRenderer(new CellRenderer());
        tableColumnD.setHeaderRenderer(new HeaderRenderer(table));
        
        TableColumn tableColumnE = table.getColumn("Spalte E");
        tableColumnE.setResizable(false);
        tableColumnE.setCellRenderer(new CellRenderer());
        tableColumnE.setHeaderRenderer(new HeaderRenderer(table));
        
        return table;
    }
    
    public class CellRenderer extends DefaultTableCellRenderer implements TableCellRenderer {
        
        public CellRenderer()
        {
            this.setHorizontalAlignment(JLabel.LEFT);
            this.setForeground(Color.black);
            this.setFont(new Font("Helvetica", Font.PLAIN,12));
            this.setOpaque(false);
        }
        
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col)
        {
            this.setText(value.toString());
            this.setSize(table.getCellRect(row, col, true).width, 16);
         
            if (hasFocus)
            	this.setBorder(BorderFactory.createLineBorder(table.getForeground(), 1));
            else
            	this.setBorder(BorderFactory.createLineBorder(table.getForeground(), 0));
            
          /*
         // Hintergrund verändern aufgrund der Position
            if (row%2==0)
                this.setIcon(Konstanten.TABLE_BACKGROUND_GERADE_ZELLEN);
            else
                this.setIcon(Konstanten.TABLE_BACKGROUND_UNGERADE_ZELLEN);
          */  
            return this;
        }
    }
    
    public class HeaderRenderer extends DefaultTableCellRenderer implements TableCellRenderer {
 
        private Icon mAscending = new AscendingIcon();
        private Icon mDescending = new DescendingIcon();
        private Icon mNull = new NullIcon();
       
        List<? extends SortKey> skeys = null;
        
        public HeaderRenderer(JTable table)
        {
            this.setHorizontalAlignment(JLabel.LEFT);
            this.setForeground(Color.blue);
            this.setFont(new Font("Helvetica", Font.BOLD,12));
            this.setOpaque(false);
            this.setHorizontalAlignment(JLabel.CENTER);
        }
        
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col)
        {
            this.setText(value.toString());
            
            //this.setIcon(Konstanten.TABLE_BACKGROUND_HEADER);
            
            skeys = table.getRowSorter().getSortKeys();
            if (skeys != null)
            {
                
                for (SortKey sortKey : skeys)
                {
                    int columnIndex = table.convertColumnIndexToView(sortKey.getColumn());
 
                     if (col == columnIndex)
                    {
                        if(sortKey.getSortOrder() == SortOrder.ASCENDING)
                        {
                            setIcon(mAscending);
                            return this;
                        }
                        else if (sortKey.getSortOrder() == SortOrder.DESCENDING)
                        {
                            setIcon(mDescending);
                            return this;
                        }
                    }
                }
            }
            setIcon(mNull);
            return this;
        }
    }
    
    public class NullIcon implements Icon
    {
        public int getIconHeight()
        {
            return 6;
        }
 
        public int getIconWidth()
        {
            return 6;
        }
 
        public void paintIcon(Component pComponent, Graphics pGraphics, int pX, int pY)
        {
        }
    }
    
    public class AscendingIcon extends NullIcon
    {
        public void paintIcon(Component pComponent, Graphics pGraphics, int pX, int pY)
        {
            int[] xx = {pX, pX + 3, pX + 6};
            int[] yy = {pY + 6, pY, pY + 6};
 
            Color initialColor = pGraphics.getColor();
            float[] initial = Color.RGBtoHSB(initialColor.getRed(), initialColor.getGreen(), initialColor.getBlue(), null);
            boolean need = initial[2] < .5f;
            initial[2] = invertAsNeed(initial[2], need);
 
            Color line = Color.getHSBColor(initial[0], initial[1], invertAsNeed(initial[2] * .7f, need));
            Color fill = Color.getHSBColor(initial[0], initial[1], invertAsNeed(initial[2] * .35f, need));
            pGraphics.setColor(fill);
            pGraphics.fillPolygon(xx, yy, 3);
            pGraphics.setColor(line);
            pGraphics.drawPolygon(xx, yy, 3);
        }
        
        private float invertAsNeed(float pBright, boolean pNeed)
        {
            return pNeed ? 1 - pBright : pBright;
        }
    }
    
    public class DescendingIcon extends NullIcon {
       public void paintIcon(Component pComponent, Graphics pGraphics, int pX,
                int pY) {
            int[] xx = {pX, pX + 3, pX + 6};
            int[] yy = {pY, pY + 6, pY + 0};
 
            Color initialColor = pGraphics.getColor();
            float[] initial = Color.RGBtoHSB(initialColor.getRed(),
                    initialColor.getGreen(), initialColor.getBlue(), null);
 
            boolean need = initial[2] < .5f;
            initial[2] = invertAsNeed(initial[2], need);
 
            Color line = Color.getHSBColor(initial[0], initial[1],
                    invertAsNeed(initial[2] * .7f, need));
            Color fill = Color.getHSBColor(initial[0], initial[1],
                    invertAsNeed(initial[2] * .35f, need));
            pGraphics.setColor(fill);
            pGraphics.fillPolygon(xx, yy, 3);
            pGraphics.setColor(line);
            pGraphics.drawPolygon(xx, yy, 3);
        }
        
        private float invertAsNeed(float pBright, boolean pNeed)
        {
            return pNeed ? 1 - pBright : pBright;
        }
    }
}
 
Ich habe die Lösung gefunden.

Java:
if (hasFocus)
{
	for (int zaehler = 0; zaehler < table.getColumnCount(); zaehler++)
	{
		table.getCellRenderer(row, zaehler).getTableCellRendererComponent(table, value, true, false, row, zaehler);
	}
}

if (isSelected)
	this.setBorder(BorderFactory.createLineBorder(table.getForeground(), 1));
else
	this.setBorder(BorderFactory.createLineBorder(table.getForeground(), 0));

Da mir im CellRenderer die Zeile bekannt ist, brauche ich nur über alle Spalten die Methode getTableCellRendererComponent mit den entsprechenden Parametern aufrufen. Die Zeilen zum SelectionMode müssen hierzu jedoch gelöscht werden.

Hier ist der GesamteTest-Code:

Java:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.List;
 
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SortOrder;
import javax.swing.RowSorter.SortKey;
import javax.swing.border.BevelBorder;
import javax.swing.border.LineBorder;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
 
public class TableDemo extends JFrame
{
    
    private TableRowSorter<TableModel> rowSorter = null;
    private JScrollPane scrollPane = null;
    
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TableDemo().setVisible(true);
            }
        });
    }
    
    public TableDemo()
    {
        super("TableDemo");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        
        getContentPane().add( getScrollPaneSpieler() );
        pack();
    }
    
    private JScrollPane getScrollPaneSpieler()
    {
        if (scrollPane == null)
        {
            scrollPane = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_NEVER,
                                                      JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            scrollPane.setOpaque(false);
            scrollPane.setBounds(new Rectangle(10, 130, 500, 300));
            scrollPane.setViewportView(getTable());
            scrollPane.getViewport().setOpaque(false); 
            scrollPane.getVerticalScrollBar().setOpaque(false);
            scrollPane.setBorder(new BevelBorder(BevelBorder.RAISED));
            scrollPane.setVisible(true);
        }   
        return scrollPane;
    }
    
    public JTable getTable()
    {
        JTable table = null;
        
        Object[][] data = new Object[][]{
                {1, 5, 8, 9, 0},
                {2, 4, 7, 7, 5},
                {3, 3, 6, 8, 6},
                {7, 5, 8, 7, 7},
                {8, 1, 1, 1, 8},
                {8, 1, 9, 3, 1},
                {8, 2, 9, 3, 4},
                {8, 8, 2, 1, 8},
                {7, 5, 8, 9, 5}
        };
        
        String[] columnNames = new String[]{
                "Spalte A", "Spalte B", "Spalte C", "Spalte D", "Spalte E"
        };
        
        table = new JTable( data, columnNames );
        table.setLayout(new BoxLayout(table, BoxLayout.Y_AXIS));
        table.setOpaque(false);
        table.setPreferredSize(new Dimension(400,250));
        table.getTableHeader().setOpaque(false);
        table.setBorder(new LineBorder(Color.gray));
        
        table.setAutoCreateRowSorter(true);
        rowSorter = new TableRowSorter<TableModel>(table.getModel());
        rowSorter.setMaxSortKeys(2);
        table.setRowSorter(rowSorter);
      
        TableColumn tableColumnA = table.getColumn("Spalte A");
        tableColumnA.setResizable(false);
        tableColumnA.setCellRenderer(new CellRenderer());
        tableColumnA.setHeaderRenderer(new HeaderRenderer(table));
        
        TableColumn tableColumnB = table.getColumn("Spalte B");
        tableColumnB.setResizable(false);
        tableColumnB.setCellRenderer(new CellRenderer());
        tableColumnB.setHeaderRenderer(new HeaderRenderer(table));
        
        TableColumn tableColumnC = table.getColumn("Spalte C");
        tableColumnC.setResizable(false);
        tableColumnC.setCellRenderer(new CellRenderer());
        tableColumnC.setHeaderRenderer(new HeaderRenderer(table));
        
        TableColumn tableColumnD = table.getColumn("Spalte D");
        tableColumnD.setResizable(false);
        tableColumnD.setCellRenderer(new CellRenderer());
        tableColumnD.setHeaderRenderer(new HeaderRenderer(table));
        
        TableColumn tableColumnE = table.getColumn("Spalte E");
        tableColumnE.setResizable(false);
        tableColumnE.setCellRenderer(new CellRenderer());
        tableColumnE.setHeaderRenderer(new HeaderRenderer(table));
        
        return table;
    }
    
    public class CellRenderer extends DefaultTableCellRenderer implements TableCellRenderer {
        
        public CellRenderer()
        {
            this.setHorizontalAlignment(JLabel.LEFT);
            this.setForeground(Color.black);
            this.setFont(new Font("Helvetica", Font.PLAIN,12));
            this.setOpaque(false);
        }
        
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col)
        {
            this.setText(value.toString());
            this.setSize(table.getCellRect(row, col, true).width, 16);
            
            if (hasFocus)
            {
            	for (int zaehler = 0; zaehler < table.getColumnCount(); zaehler++)
            	{
            		table.getCellRenderer(row, zaehler).getTableCellRendererComponent(table, value, true, false, row, zaehler);
            	}
            }
            
            if (isSelected)
            	this.setBorder(BorderFactory.createLineBorder(table.getForeground(), 1));
            else
            	this.setBorder(BorderFactory.createLineBorder(table.getForeground(), 0));
            
          /*
         // Hintergrund verändern aufgrund der Position
            if (row%2==0)
                this.setIcon(Konstanten.TABLE_BACKGROUND_GERADE_ZELLEN);
            else
                this.setIcon(Konstanten.TABLE_BACKGROUND_UNGERADE_ZELLEN);
          */  
            return this;
        }
    }
    
    public class HeaderRenderer extends DefaultTableCellRenderer implements TableCellRenderer {
 
        private Icon mAscending = new AscendingIcon();
        private Icon mDescending = new DescendingIcon();
        private Icon mNull = new NullIcon();
       
        List<? extends SortKey> skeys = null;
        
        public HeaderRenderer(JTable table)
        {
            this.setHorizontalAlignment(JLabel.LEFT);
            this.setForeground(Color.blue);
            this.setFont(new Font("Helvetica", Font.BOLD,12));
            this.setOpaque(false);
            this.setHorizontalAlignment(JLabel.CENTER);
        }
        
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col)
        {
            this.setText(value.toString());
            
            //this.setIcon(Konstanten.TABLE_BACKGROUND_HEADER);
            
            skeys = table.getRowSorter().getSortKeys();
            if (skeys != null)
            {
                
                for (SortKey sortKey : skeys)
                {
                    int columnIndex = table.convertColumnIndexToView(sortKey.getColumn());
 
                     if (col == columnIndex)
                    {
                        if(sortKey.getSortOrder() == SortOrder.ASCENDING)
                        {
                            setIcon(mAscending);
                            return this;
                        }
                        else if (sortKey.getSortOrder() == SortOrder.DESCENDING)
                        {
                            setIcon(mDescending);
                            return this;
                        }
                    }
                }
            }
            setIcon(mNull);
            return this;
        }
    }
    
    public class NullIcon implements Icon
    {
        public int getIconHeight()
        {
            return 6;
        }
 
        public int getIconWidth()
        {
            return 6;
        }
 
        public void paintIcon(Component pComponent, Graphics pGraphics, int pX, int pY)
        {
        }
    }
    
    public class AscendingIcon extends NullIcon
    {
        public void paintIcon(Component pComponent, Graphics pGraphics, int pX, int pY)
        {
            int[] xx = {pX, pX + 3, pX + 6};
            int[] yy = {pY + 6, pY, pY + 6};
 
            Color initialColor = pGraphics.getColor();
            float[] initial = Color.RGBtoHSB(initialColor.getRed(), initialColor.getGreen(), initialColor.getBlue(), null);
            boolean need = initial[2] < .5f;
            initial[2] = invertAsNeed(initial[2], need);
 
            Color line = Color.getHSBColor(initial[0], initial[1], invertAsNeed(initial[2] * .7f, need));
            Color fill = Color.getHSBColor(initial[0], initial[1], invertAsNeed(initial[2] * .35f, need));
            pGraphics.setColor(fill);
            pGraphics.fillPolygon(xx, yy, 3);
            pGraphics.setColor(line);
            pGraphics.drawPolygon(xx, yy, 3);
        }
        
        private float invertAsNeed(float pBright, boolean pNeed)
        {
            return pNeed ? 1 - pBright : pBright;
        }
    }
    
    public class DescendingIcon extends NullIcon {
       public void paintIcon(Component pComponent, Graphics pGraphics, int pX,
                int pY) {
            int[] xx = {pX, pX + 3, pX + 6};
            int[] yy = {pY, pY + 6, pY + 0};
 
            Color initialColor = pGraphics.getColor();
            float[] initial = Color.RGBtoHSB(initialColor.getRed(),
                    initialColor.getGreen(), initialColor.getBlue(), null);
 
            boolean need = initial[2] < .5f;
            initial[2] = invertAsNeed(initial[2], need);
 
            Color line = Color.getHSBColor(initial[0], initial[1],
                    invertAsNeed(initial[2] * .7f, need));
            Color fill = Color.getHSBColor(initial[0], initial[1],
                    invertAsNeed(initial[2] * .35f, need));
            pGraphics.setColor(fill);
            pGraphics.fillPolygon(xx, yy, 3);
            pGraphics.setColor(line);
            pGraphics.drawPolygon(xx, yy, 3);
        }
        
        private float invertAsNeed(float pBright, boolean pNeed)
        {
            return pNeed ? 1 - pBright : pBright;
        }
    }
}
 
Ein kleiner Fehler war noch drin. Damit man mit den Datentypen der Values keine Probleme bekommt sollte die Lösung wie folgt aussehen:

Java:
if (hasFocus)
{
	for (int zaehler = 0; zaehler < table.getColumnCount(); zaehler++)
	{
		table.getCellRenderer(row, zaehler).getTableCellRendererComponent(table, table.getValueAt(row, zaehler), true, false, row, zaehler);
	}
}

if (isSelected)
	this.setBorder(BorderFactory.createLineBorder(table.getForeground(), 1));
else
	this.setBorder(BorderFactory.createLineBorder(table.getForeground(), 0));
 

Zurück
Oben