Tableheader,Scrollpane und repaintproblem

cr3m4

Mitglied
Hallo,

also ich blicke bei der repaintfunktion noch nicht so ganz durch.
Folgendes Problem:

ich habe eine JTable mit eigenem Cellrenderer und HeaderRenderer die bei jeder dritten Spalte eine BorderLinie zeichnet.
Wenn ich dann scrolle, wird der Header nicht korrekt dargestellt. Wo das repaint korrekt zu setzen ist oder irgendwelche besseren Methoden zur korrekten Darstellung entziehen sich leider meiner Kenntnis.

Hier ein Beispiel:
repaint-bsp.JPG

und hier Die Renderer:

Code:
 class MultiLineHeaderRenderer extends JLabel implements TableCellRenderer
	  {
			private static final long	serialVersionUID	= 1L;

				public MultiLineHeaderRenderer() 
					{
					setOpaque(true);
					setForeground(UIManager.getColor("TableHeader.foreground"));
					setBackground(UIManager.getColor("TableHeader.background"));
					setBorder(null);
					
					setVerticalAlignment(CENTER);
					setHorizontalAlignment(CENTER);
					setVerticalTextPosition(CENTER);
					setHorizontalTextPosition(CENTER);
					
					setFont(new Font("Arial",1,12));
					}

				public Component getTableCellRendererComponent(JTable table, Object value,
						       boolean isSelected, boolean hasFocus, int row, int column)
				{
				   
					table.getTableHeader().setPreferredSize(new Dimension(0,30));
					
					setBorder(new MatteBorder(0,1,0,0,Color.BLACK));
					
					setText(value.toString());
					repaint();
					return this ;
				}
		}

Code:
  class noLineHeaderRenderer extends JLabel implements TableCellRenderer {
			
			private static final long	serialVersionUID	= 1L;

				public noLineHeaderRenderer() 
					{
					setOpaque(true);
					setForeground(UIManager.getColor("TableHeader.foreground"));
					setBackground(UIManager.getColor("TableHeader.background"));
					setBorder(null);
					
					setVerticalAlignment(CENTER);
					setHorizontalAlignment(CENTER);
					setVerticalTextPosition(CENTER);
					setHorizontalTextPosition(CENTER);
					
					setFont(new Font("Arial",1,12));
					
					}

				public Component getTableCellRendererComponent(JTable table, Object value,
						       boolean isSelected, boolean hasFocus, int row, int column)
				{
					table.getTableHeader().setPreferredSize(new Dimension(0,30));
					
					setBorder(new MatteBorder(0,0,0,0,Color.BLACK));
			
					setText(value.toString());
					repaint();
					return this ;
				}
		}

Hier die Übergabe der Renderer:

Code:
MultiLineHeaderRenderer lineRenderer = new MultiLineHeaderRenderer();
noLineHeaderRenderer noLineRenderer = new noLineHeaderRenderer();
							
	for (int i=0;i<jTable.getColumnCount();i++)
		{
		packColumn(umlaufPlan_jTable,i,5);
		if(i%3==0)
		{
			TableColumn col = jTable.getColumnModel().getColumn(i);
			col.setHeaderRenderer(lineRenderer);
		}
		else
			{
			TableColumn col = jTable.getColumnModel().getColumn(i);
                        col.setHeaderRenderer(noLineRenderer);	
			}
	}
 
Hallo,

so auf den ersten Blick konnte ich mal keinen Fehler entdecken. Die repaint()-Aufrufe kannst du löschen, die brauchst du nicht.

MFG

Sascha
 
Versuch es mal so. Da ich leider den kompletten Source-Code nicht habe, kann ich es leider auch nicht testen. Aber die Klassen sind so besser, als vorher.

Java:
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;

import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.border.MatteBorder;
import javax.swing.table.TableCellRenderer;

class MultiLineHeaderRenderer
    extends JLabel
    implements TableCellRenderer
{
  private static final long serialVersionUID = 1L;

  public MultiLineHeaderRenderer()
  {
    setOpaque(true);
    setForeground(UIManager.getColor("TableHeader.foreground"));
    setBackground(UIManager.getColor("TableHeader.background"));
    setBorder(null);

    setVerticalAlignment(CENTER);
    setHorizontalAlignment(CENTER);
    setVerticalTextPosition(CENTER);
    setHorizontalTextPosition(CENTER);

    setFont(new Font("Arial", 1, 12));
    
    setBorder(new MatteBorder(0, 1, 0, 0, Color.BLACK));
  }

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

Java:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;

import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.border.MatteBorder;
import javax.swing.table.TableCellRenderer;

class NoLineHeaderRenderer
    extends JLabel
    implements TableCellRenderer
{

  private static final long serialVersionUID = 1L;

  public NoLineHeaderRenderer()
  {
    setOpaque(true);
    setForeground(UIManager.getColor("TableHeader.foreground"));
    setBackground(UIManager.getColor("TableHeader.background"));
    setBorder(null);

    setVerticalAlignment(CENTER);
    setHorizontalAlignment(CENTER);
    setVerticalTextPosition(CENTER);
    setHorizontalTextPosition(CENTER);

    setFont(new Font("Arial", 1, 12));
    setBorder(new MatteBorder(0, 0, 0, 0, Color.BLACK));
  }

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

    setText(value.toString());

    return this;
  }
}

Code:
MultiLineHeaderRenderer lineRenderer = new MultiLineHeaderRenderer();
    NoLineHeaderRenderer noLineRenderer = new NoLineHeaderRenderer();
    jTable.getTableHeader().setPreferredSize(new Dimension(0,30));
    
                  
      for (int i=0;i<jTable.getColumnCount();i++)
        {
        packColumn(umlaufPlan_jTable,i,5);
        if(i%3==0)
        {
          TableColumn col = jTable.getColumnModel().getColumn(i);
          col.setHeaderRenderer(lineRenderer);
        }
        else
          {
          TableColumn col = jTable.getColumnModel().getColumn(i);
                            col.setHeaderRenderer(noLineRenderer);  
          }
      }

MFG

Sascha
 
Hab hier nochmal einen Vorschlag. So dürftest du auch nur mit einem Renderer auskommen.

Java:
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;

import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.border.MatteBorder;
import javax.swing.table.TableCellRenderer;

class LineHeaderRenderer
    extends JLabel
    implements TableCellRenderer
{

  private static final long serialVersionUID = 1L;
  
  private MyMatteBorder border = null;

  public LineHeaderRenderer()
  {
    setOpaque(true);
    setForeground(UIManager.getColor("TableHeader.foreground"));
    setBackground(UIManager.getColor("TableHeader.background"));

    setVerticalAlignment(CENTER);
    setHorizontalAlignment(CENTER);
    setVerticalTextPosition(CENTER);
    setHorizontalTextPosition(CENTER);

    border = new MyMatteBorder(0, 1, 0, 0, Color.BLACK);
    
    setFont(new Font("Arial", 1, 12));
    setBorder(border);
  }

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

    setText(value.toString());
    border.setColumn(column);
    return this;
  }
  
  private class MyMatteBorder extends MatteBorder{
    
    private int column = 0;

    public MyMatteBorder(int top, int left, int bottom, int right, Color matteColor)
    {
      super(top, left, bottom, right, matteColor);
    }
    
    @Override
    public boolean isBorderOpaque()
    {
      return super.isBorderOpaque() && column % 3 == 0;
    }

    /**
     * @return the column
     */
    public int getColumn()
    {
      return column;
    }

    /**
     * @param column the column to set
     */
    public void setColumn(int column)
    {
      this.column = column;
    }
  }
}
Code:
LineHeaderRenderer lineRenderer = new LineHeaderRenderer();
      jTable.getTableHeader().setPreferredSize(new Dimension(0,30));
    
                  
      for (int i=0;i<jTable.getColumnCount();i++)
        {
        packColumn(umlaufPlan_jTable,i,5);
                TableColumn col = jTable.getColumnModel().getColumn(i);
          col.setHeaderRenderer(lineRenderer);
             }

MFG

Sascha
 
hmm, scheint nicht zu funktionieren. mit dem Renderer werden auch bei jeder Spalte eine Borderlinie gezeichnet.
zudem besteht das repaintProblem noch immer.


hier einmal die komplette Tabelle, vielleicht liegt ja dort der Hase im Pfeffer:

Code:
  TableModel jTableModel = CreateTableModel(tablepath);
  jTable = new JTable();

  Table_jScrollPane.setViewportView(jTable);
  
  
  
  jTable.setModel(jTableModel);
  jTable.setFont(new java.awt.Font("Arial",0,14));
  jTable.setShowGrid(false);
  
  jTable.setIntercellSpacing(new java.awt.Dimension(0, 0));
  
  jTable.setCellEditor(new noCellEdit());
  
  /* ****** alter Renderer ********
  MultiLineHeaderRenderer lineRenderer = new MultiLineHeaderRenderer();
  noLineHeaderRenderer noLineRenderer = new noLineHeaderRenderer();
  

  for (int i=0;i<jTable.getColumnCount();i++)
  {
   	packColumn(jTable,i,5);

   	if(i%3==0)
   	{
   	TableColumn col = jTable.getColumnModel().getColumn(i);
  	col.setHeaderRenderer(lineRenderer);

   	}
   	else
   	{
   	TableColumn col = jTable.getColumnModel().getColumn(i);
   	col.setHeaderRenderer(noLineRenderer);
  	
  	}
  }
  ******************/
  /************ Renderer von Sascha **************/
  LineHeaderRenderer lineRenderer = new LineHeaderRenderer();
  jTable.getTableHeader().setPreferredSize(new Dimension(0,30));
 		    
 		                  
 		      for (int i=0;i<jTable.getColumnCount();i++)
 		        {
 		        packColumn(jTable,i,5);
 		        
 		        TableColumn col = jTable.getColumnModel().getColumn(i);
 		        col.setHeaderRenderer(lineRenderer);
 		        }

  
  jTable.setDefaultRenderer(Object.class, new tRender());
  jTable.setShowGrid(false);
  jTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);


Ich hätte noch die Idee, die Scrollaktion abzufangen und dabei ein repaint aufzurufen.
Also in der Art:

if (jscrollPane.scrolltgerade)
repaint

oder
if (alteposition!=neueposition)
repaint

gibts denn eine Methode die die Scrollbarposition übergibt?
 
Versuch es jetzt nochmal.


Code:
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics;

import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.border.MatteBorder;
import javax.swing.table.TableCellRenderer;

public class LineHeaderRenderer
    extends JLabel
    implements TableCellRenderer
{

  private static final long serialVersionUID = 1L;
  
  private MyMatteBorder border = null;

  public LineHeaderRenderer()
  {
    setOpaque(true);
    setForeground(UIManager.getColor("TableHeader.foreground"));
    setBackground(UIManager.getColor("TableHeader.background"));

    setVerticalAlignment(CENTER);
    setHorizontalAlignment(CENTER);
    setVerticalTextPosition(CENTER);
    setHorizontalTextPosition(CENTER);

    border = new MyMatteBorder(0, 1, 0, 0, Color.BLACK);
    
    setFont(new Font("Arial", 1, 12));
    setBorder(border);
  }

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

    setText(value.toString());
    border.setColumn(column);
    return this;
  }
  
  private class MyMatteBorder extends MatteBorder{
    
    private int column = 0;

    public MyMatteBorder(int top, int left, int bottom, int right, Color matteColor)
    {
      super(top, left, bottom, right, matteColor);
    }
    
    @Override
    public boolean isBorderOpaque()
    {
      return super.isBorderOpaque() && column % 3 == 0;
    }

    /**
     * @return the column
     */
    public int getColumn()
    {
      return column;
    }
    
    

    /**
     * @param column the column to set
     */
    public void setColumn(int column)
    {
      this.column = column;
    }
    
    @Override
    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height)
    {
      if(isBorderOpaque())
      super.paintBorder(c, g, x, y, width, height);
    }
  }
}

Es liegt nicht an den Renderern. Hab mal schnell ein kleines Beispiel geschrieben und bei mir funktioniert es. Poste am besten mal den kompletten Source-code oder lass mir mal das Project zukommen.

MFG

Sascha
 
Also die Linien bei jeder dritten Spalte stimmen schonmal:)

anbei hier mal der komplette quellcode.
Anhang anzeigen umlauf-bsp.zip

Bitte nicht über die QuelltextStruktur wundern, bin noch blutiger Anfänger wie du vielleicht bemerkt hast :)

p.s.: du müsstest evtl den Pfad zur csv-Datei anpassen.
 
Es liegt an dieser Zeile. Ich kann im Moment aber noch nicht sagen warum. :)

Code:
umlaufPlan_jTable.getTableHeader().setPreferredSize(new Dimension(0, 30));

Aus irgendeinem Grund wird der Header nicht neu gezeichnet, wenn diese Zeile drin steht.

Du könntest es aber so machen. Du löschst die Zeile oben und fügst diese Zeile
Code:
setPreferredSize(new Dimension(0,30));
in den Konstruktor meines CellRenderers ein.

MFG

Sascha

EDIT: Das ist ein Bug
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4473075

Du kannst entweder meine Lösung nehmen oder das was Bug-Report beschrieben wird.
 
Zurück