Problem mit MultiLineCellRenderer

goory6771

Grünschnabel
Hallo,

wie schon oben stehen habe ich ein Problem mit meinem MultiLineCellRenderer.
Lege meinen MultiLineCellRenderer auf die Spalten Benennung und Bemerkung. Beide Spalten liegen in einer Zeile.

Problem:
Wenn beide Spalten einen langen Text haben, sehe ich den gesamten Text beider Spalten und wenn nur die Spalte Bemerkung einen langen Text hat sehe ich auch den gesamten Text der Spalte Bemerkung.

Aber hat nur die Spalte Benennung einen langen Text und die Spalte Bemerkung nicht, sehe ich nicht den gesamten Text von der Spalte Benennung.

Weis jemand warum

Bild1.jpg

Bild2.jpg

Bild3.jpg

Hier noch mein Quelltext für den MultiLineCellRenderer:
public static class MultiLineCellRenderer extends JTextArea implements TableCellRenderer
{
protected static Border noFocusBorder;

private Color unselectedForeground;
private Color unselectedBackground;

public MultiLineCellRenderer() {
super();
noFocusBorder = new EmptyBorder(1, 2, 1, 2);
setLineWrap(true);
setWrapStyleWord(true);
setOpaque(true);
setBorder(noFocusBorder);
}

public void setForeground(Color c) {
super.setForeground(c);
unselectedForeground = c;
}

public void setBackground(Color c) {
super.setBackground(c);
unselectedBackground = c;
}

public void updateUI() {
super.updateUI();
setForeground(null);
setBackground(null);
}

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

if (isSelected) {
super.setForeground(table.getSelectionForeground());
super.setBackground(table.getSelectionBackground());
}
else {
super.setForeground((unselectedForeground != null) ? unselectedForeground
: table.getForeground());
super.setBackground((unselectedBackground != null) ? unselectedBackground
: table.getBackground());
}

setFont(table.getFont());

if (hasFocus) {
setBorder( UIManager.getBorder("Table.focusCellHighlightBorder") );
if (!isSelected && table.isCellEditable(row, column)) {
super.setForeground( UIManager.getColor("Table.focusCellForeground") );
super.setBackground( UIManager.getColor("Table.focusCellBackground") );
}
} else {
setBorder(noFocusBorder);
}
setValue(table, row, column, value);
return this;
}

protected void setValue(JTable table, int row, int column, Object value)
{
if(value!= null)
{
String text = value.toString();
setText(text);
View view = getUI().getRootView(this);
view.setSize((float) table.getColumnModel().getColumn(column).getWidth() -3, -1);
float y = view.getPreferredSpan(View.Y_AXIS);
int h = (int) Math.ceil(y + 3);
if(table.getRowHeight(row) != h)
{
table.setRowHeight(row,h);
}
else
{
setText(text);
}
}
}
}
 
hast Du schonmal versucht zu tracen, oder Properties Deines MultilineCellRenderers auf die Console rauszuschreiben? Hast Du mal geschaut was passiert, wenn Du die Zeile selektierst?
Pauschal habe ich gerade mal in Deinem Quelltext geschaut gehabt, ob es da ein Farbproblem gibt, also es sieht erstmal schlüssig aus, wenn ich nicht was übersehen haben sollte :-/

Sooo mir ist nach Formatierren Deines Quelltextes die Rotine
Java:
                protected void setValue(JTable table, int row, int column, Object value)
	{
		if (value != null)
		{
			String text = value.toString();
			setText(text);
			View view = getUI().getRootView(this);
			view.setSize((float) table.getColumnModel().getColumn(column).getWidth() - 3, -1);
			float y = view.getPreferredSpan(View.Y_AXIS);
			int h = (int) Math.ceil(y + 3);
			if (table.getRowHeight(row) != h)
			{
				table.setRowHeight(row, h);
			}
			else
			{
				setText(text);
			}
		}
	}
aufgefallen Du verwendest 2 mal setText(text) kann es sein das wenn du die Höhe der Tabellen zeile änderst das erste setText(text) irgendwie irgnoriert oder überspuhlt wird?
versuche doch auch ein setText(text) probehalber nach dem setRowHight(row,h) zu machen und schau ob das besser wird
Ist aber nur so ein ad hoc aus dem Bauch raus.

Nachtrag:
Weiß ja nicht ob sich der Verdacht bestätigt, jedoch erscheint es für mich möglicherweise unoptimiert
die Routine setRowHight(..) innerhalb eines Renderers aufzurufen, da es dort wieder zu einem repaint führt (so ich es richtig verstehe)
Java:
    public void setRowHeight(int row, int rowHeight) {
        if (rowHeight <= 0) {
            throw new IllegalArgumentException("New row height less than 1");
        }
	getRowModel().setSize(row, rowHeight);
        if (sortManager != null) {
            sortManager.setViewRowHeight(row, rowHeight);
        }
	resizeAndRepaint();
    }
Bin mal gespannt, was passieren würde, wenn Du das setRowHeight nicht in dem Renderer steckst sonders irgend woanders gesondert.
 
Zuletzt bearbeitet:
Hi,

das erste setText(text) befüllt meine Tabelle. Es gibt mir für jede Zeile in meiner JTable den Text, und das zweite setText(text) überschreibt es dann, wenn ich den Text ändere!

Ruf über die Funktion
table.getColumnModel().getColumn(1).setCellRenderer(new TextTableCellRenderer()); meine MultiLineCellRender im Konstruktor auf.
Mir ist aufgefallen das, als ich mein zweites setText(text) über die Konsole ausgegeben habe, das es immer, und immer wieder aufgerufen wird!
Dachte mir das das nur einmal geschiet, das es ja im Konstruktor aufgerufen wird. Oder verstehe ich da was falsch?

Ich glaub ich hab mein Problem falsch beschrieben.
Mein Problem ist, dass der MultiLineCellRender, Zelle für Zelle abfragt und sie dann nacheinander setzt. Wenn dann die letzte Zelle weniger Zeilen für den Text benötigt als die erste Zelle, ist die Zellenhöhe wieder niedriger.

Ich weis was ich jetzt machen muss, ich muss abfragen, in welcher Zelle der längste Text ist, und dann alle Zellen die gleiche Höhe zuweisen! Oder liege ich damit falsch
 
Zuletzt bearbeitet:
Hi,

das erste setText(text) befüllt meine Tabelle. Es gibt mir für jede Zeile in meiner JTable den Text, und das zweite setText(text) überschreibt es dann, wenn ich den Text ändere!
Hmmm .... das verstehe ich nicht ganz. In der Routine änderst Du den Text doch gar nicht, sondern Du schreibst ihn zweimal in die Komponente. beim ersten mal unbedingt und beim 2. Mal bedingt in Bezug auf Zeilenhöhe, welches aber aus meinem Verständnis heraus nicht so ganz Sinnvoll erscheint, denn Du setzt den selben Text einfach nochmal.

Ruf über die Funktion
table.getColumnModel().getColumn(1).setCellRenderer(new TextTableCellRenderer()); meine MultiLineCellRender im Konstruktor auf.
Mir ist aufgefallen das, als ich mein zweites setText(text) über die Konsole ausgegeben habe, das es immer, und immer wieder aufgerufen wird!
Dachte mir das das nur einmal geschiet, das es ja im Konstruktor aufgerufen wird. Oder verstehe ich da was falsch?
Wie schon in meiner vorherigen Mail dargebracht, kann ein neues repaint entstehen wegen dem Aufruf von setRowHeight().
Ich selbst würde die Zeilenhöhe aus deisem Grund nicht im Cell-Renderer abwickeln wollen, da man solche Zyklen, vermute ich mal, nur umständlich in den Griff bekommt.
Der Konstructor eines Zellrenderers löst eigentlich kein repaint() aus, dass würde sonst Zyklen (Endlosschleife) nach sich ziehen. ein Renderer wird nur verwendet um einen Teil des Repaints durchzuführen. Für gewöhnlich wird ein Zellrenderer nur einmal instanziiert um ihn als Stempel wieder zu verwenden, so dass nur lediglich sein Wert, der gerendert werden soll, beim Durchiterieren der Tables sich ändert.

Ich glaub ich hab mein Problem falsch beschrieben.
Mein Problem ist, dass der MultiLineCellRender, Zelle für Zelle abfragt und sie dann nacheinander setzt. Wenn dann die letzte Zelle weniger Zeilen für den Text benötigt als die erste Zelle, ist die Zellenhöhe wieder niedriger.

Ahh nun glaube ich eher zu verstehen, was Deine Beobachtungen bezüglich der Zeilenhöhe sind.

Ich weis was ich jetzt machen muss, ich muss abfragen, in welcher Zelle der längste Text ist, und dann alle Zellen die gleiche Höhe zuweisen! Oder liege ich damit falsch
Es ist sicher eine Möglichkeit das auszuprobieren. Ich selbst hätte jedoch da einen anderen Lösungsvorschlag.
Immer dann wenn sich der Inhalt ändert sollte die Zeilenhöhe kontrolliert werden und nicht dann wenn die Zelle dargestellt wird. Also wenn Du einen Dialog hast oder einen Cell-Editor um die Inhalte Deiner Tabelle zu ändern, und das Editieren abgechlossen ist, dann prüfst Du die Zeilenhöhe und veränderst sie gegbenenfalls.
 
Zuletzt bearbeitet:
Hi,

habs jetzt hinbekommen!

Werds aber auch mal mit deinem Vorschlag versuchen, erst dann das setText(text) aufzurufen, wenn ich den Dialog beende, damit nicht immer das repaint aufgraufen wird!

Hoffe das es der Performance zugute kommt!! :rolleyes:
 
Hi,

habs jetzt hinbekommen!

Werds aber auch mal mit deinem Vorschlag versuchen, erst dann das setText(text) aufzurufen, wenn ich den Dialog beende, damit nicht immer das repaint aufgraufen wird!

Hoffe das es der Performance zugute kommt!! :rolleyes:

Hmmm jetz habe ich den Eindruck, Du hast mich nicht richtig verstanden.
Ich nehme (hoffe) Du meintest hier anstelle von setText() aufrufen das Kontrollieren und justieren der Zeilenhöhe und hast Dich nur verschieben ;)
 
Zurück