Swing ListCellRenderer und LookAndFeel

hdi

Top Contributor
Hey,

ich steh grad vor einem Verständnisproblem in Bezug auf den ListCellRenderer einer JList und einem externen Look And Feel. Ich nutze ein LAF des Substance Pakets, genauer das SubstanceGraphiteAquaLookAndFeel. Das sieht so aus dass er die Listeneinträge bei der Auswahl blau unterlegt, und auch beim Mouse-Over einen blauen Effekt ein-/ausblendet. Also der CellRenderer reagiert nicht nur auf Klicks, sondern eben auch auf mouseEntered/mouseExited.

Soweit als Info. Ich hab jetzt in meinem Programm eine JList, per Default-Konstruktor:

Java:
JList list = new JList();

Ich hab grad etwas den Source Code von JList überflogen, ist recht verwirrend :D Es gibt da zumindest eine updateUI() Methode, und irgendwas vonwegen setUI((ListUI)UIManager.getUI(this));, naja wie auch immer. In dem Zuge der JList Erstellung wird ja wohl irgendwo auch ein standard-mässiger ListCellRenderer zugewiesen, und der kommt ja offensichtlich aus dem LAF.

Jetzt versuche ich, den CellRenderer etwas abzuändern, denn ich möchte bei jedem Listenelement vor dem Text zudem noch ein kleines Icon anzeigen. Ich muss auf dem bestehenden CellRenderer aufbauen, weil ich ja keine Ahnung habe wie genau der Code davon aussieht, deshalb hab ich mal so anfgefangen:

Java:
public class MyListCellRenderer implements ListCellRenderer {

	private ListCellRenderer original;

	public MyListCellRenderer(ListCellRenderer original) {
		this.original = original;
	}

	@Override
	public Component getListCellRendererComponent(JList list, Object value,
			int index, boolean isSelected, boolean cellHasFocus) {

		return original.getListCellRendererComponent(list, value, index,
				isSelected, cellHasFocus);
	}
}

Im Programm dann:

Java:
JList list = new JList();
list.setCellRenderer(new MyListCellRenderer(list.getCellRenderer()));

Da das Interface ListCellRenderer ja nur diese eine obige Methode vorschreibt, und ich in dieser Methode nix weiter mach als das zu returnen, was der alte CellRenderer auch schon zurückliefert,habe ich eigentlich erwartet dass das erstmal gar keinen Unterschied macht.

Stimmt aber nicht: Zwar sehen die Einträge "statisch" noch so aus wie vorher, auch wenn sie markiert sind, allerdings sind die Effekte beim Mouse-Over weg. Versteh ich nicht.. Ich dachte es liegt halt ein MouseListener auf der Component, die die getListCellRenderer() Methode dieses CellRenderers returned. Aber das ist ja offensichtlich nicht so, weil der jetzt scheinbar weg ist.

Also ist die erste Frage: Wo ist der hin? Bzw wo kam der denn usprünglich her?

Naja ok, dachte ich mir erstmal die Mouse-Over Effekte sind nicht so wichtig, ansonsten sieht's ja noch gleich aus, die Elemente sind beim Anwählen ja schon noch mit dem selben blauen Effekt hinterlegt wie schon ursprünglich. Also wollte ich nun mein Icon davorklatschen (erstmal ein JLabel mit Text statt Icon, testweise) und ändere meine Klasse:

Java:
public class MyListCellRenderer extends JPanel implements ListCellRenderer {

	private ListCellRenderer original;
	private JLabel iconLabel;

	public MyListCellRenderer(ListCellRenderer original) {
		this.original = original;
		iconLabel = new JLabel("TEST");
		setLayout(new FlowLayout(FlowLayout.LEADING, 0, 0));
		add(iconLabel);
	}

	@Override
	public Component getListCellRendererComponent(JList list, Object value,
			int index, boolean isSelected, boolean cellHasFocus) {

		Component c = original.getListCellRendererComponent(list, value, index,
				isSelected, cellHasFocus);
		add(c);
		return this;
	}
}

Über zwei Dinge hab ich mich gewundert als ich das Programm dann gestartet hab:
1) dachte ich eigentlich dass nach jedem GUI Update die "c"-Komponente mehrmals hintereinander angezeigt wird, denn immerhin mach ich bei jedem Methodenaufruf ein add(c), aber niemals ein remove. Aber ich schätze diese Methode ist ja sowas wie paintComponent() und wird zur Laufzeit immer wieder aufgerufen. Das wär meine zweite Frage.

Aber noch viel verwrrender: Jetzt fehlen auf einmal wirklich sämtliche Effekte, "c" enthält scheinbar wirklich nur den String (bzw halt ein kleines JLabel), den die toString() Methode meiner Listenobjekte zurückliefert. Von blauer Markierung whatsoever keine Spur mehr...

Also ich peil das nicht.. Wenn der CellRenderer gar nicht für all diese Effekte zuständig ist, wer denn dann? Das ist meine dritte Frage.

Ich weiß jetzt gar nicht ob das hier nur so der Fall ist da ich ein externes LAF nutze, oder ob das jetzt mit Java-eigenen LAF's auch so ist.

Ich hoffe ihr könnt mir meine Fragen beantworten!

Danke!
 
Zuletzt bearbeitet:

hdi

Top Contributor
Ok sorry nach etwas Überlegung und Recherche kann ich mir meine zweite Frage selbst beantworten.

die add() Methode einer Component kommt ja von der Klasse Container, und ist eigentlich nur eine Delegation an die Methode addImpl(), und bei der steht dabei:

If the component is not an ancestor of this container and has a non-null parent, it is removed from its current parent before it is added to this container.

Also checkt er wohl per equals() dass "c" schon geaddet wurde und demnach wird es nicht öfters aufs Panel gelegt.

Bleiben noch die anderen Fragen :)
 

KrokoDiehl

Top Contributor
Ohne hansmuellers Verweis nun vollständig gelesen zu haben, frage ich mich, ob es notwendig ist als Renderer ein Panel zu nehmen. Der Standardrenderer verwendet ein Label und auch hier hat man ja die Möglichkeit, ein Icon zu setzen, wenn dies die Anforderung ist.
Vielleicht kannst du deinen Renderer direkt vom DefaultListCellRenderer erben lassen und erhältst so auch die L&F-typischen Effekte.
 

hansmueller

Bekanntes Mitglied
Hallo,

@KrokoDiehl:
In dem vom mir verlinkten Thema sind eine Menge verschiederner Beispiele. Ich habe nämlich das Gefühl, daß hdi die Sache etwas zu kompliziert angeht.
Zumal gibt es in dem Thema einen Link auf ein deutschsprachiges Tutorial, welches ziemlich gut erklärt, wie man mit einem ListCellRenderer umgeht, wenn man ein JLabel mit Bild und Text haben will. (coding:java:java_tut_7 [thwiki])

Das mit den DefaultListCellRenderer ist eine Idee... aber man muß dabei die getListCellRendererComponent-Methode nicht trotzdem überschreiben, um die Bilder rein zu kriegen?
Dann ist es eigenlich egal, ob man jetzt von einem JPanel/JLabel erbt und einen ListCellRenderer implementiert oder nur von dem DefaultListCellRenderer erbt.

MfG
hansmueller
 

hdi

Top Contributor
DefaultListCellRenderer ist leider nicht, hab ich auch schon versucht, da fehlen die meisten Effekte auch.

Das mit dem JPanel statt Label hab ich deswegen gemacht da ich ja die Komponente des ursprünglichen Renderers mit drin haben wollte. Man kann ja in ein Label nicht irgendwie noch ein Label packen..

Aber solche Dinge brauch ich gar nicht erst versuchen solange ich nicht rausgefunden hab wo die MouseListener liegen die da noch die Finger drin haben...

Auf jeden Fall danke für den Link, ich hatte noch keine Zeit mir das genau anzusehen, werd ich aber nachholen.
 
Zuletzt bearbeitet:

hdi

Top Contributor
@hansmueller
Ich hab mir den verlinkten Thread jetzt mal durchgelesen. Ich glaube aber, du hast nicht ganz verstanden wo mein Problem liegt ;) Ich weiß schon was ein CellRenderer ist und wie ich einen implementieren kann, ich würde auch niemals wie in dem o.g. Thread anfangen, meine Daten von JPanel erben zu lassen ;) Also ich versteh das schon...

Mein Problem ist folgendes: Ich verstehe nicht wieso mein eigener CellRenderer alle Effekte des standardmäßigen CellRenderers vom Look & Feel über Bord wirft, obwohl ja die getCellRendererComponent() genau das returned, was dieser ursprüngliche CellRenderer returned. Kuck dir mal meinen Code nochmal an bitte. Ich frage mich: Wenn die Effekte nicht von dort kommen, ja woher denn bitte dann? Immerhin dachte ich der CellRenderer rendered die Cell ;) Aber irgendie müssen da noch andre Instanzen ihre finger drin haben...

Oder kurz gesagt: Ich hab kein Problem damit, einen komplett eigenen Renderer zu schreiben, ich habe ein Problem damit den defaultmäßigen Renderer des Look & Feel zu modifizieren.
 

hansmueller

Bekanntes Mitglied
Ok,

ich glaube jetzt habe ich verstanden was du willst.

Also wenn ich richtig liege, dann ist für die Mouseover-Effekte folgende Klasse aus dem Substance Paketes zuständig:
substance sourcecode, SubstanceListUI_8java-source.html, 5.3-1

Der Renderer für diese L&F sieht so aus:
substance sourcecode, SubstanceDefaultListCellRenderer_8java-source.html, 5.3-1

Wenn du jetzt eine Liste mit den gleichen Effekten willst, muß in deiner von der oben stehenden Klasse abgeleiteten Renderer das Gleiche in der getListCellRendererComponent-Methode stehen wie im Orginal PLUS deine Ergänzung, damit du ein Label benutzen kannst. Wenn ich es richtig sehe, must du eigendlich nur den Codeabschnitt
Java:
 if (value instanceof Icon) {
                  this.setIcon((Icon) value);
                  this.setText("");
            } else {
                  this.setIcon(null);
                  this.setText((value == null) ? "" : value.toString());
            }
so abändern, daß er statt eines Icons ein JLabel will und daraus das Icon und den Text extrahierst und entsprechens setzt. Denn wie KrokoDiehl schon geschrieben hat:
KrokoDiehl hat gesagt.:
Der Standardrenderer verwendet ein Label und auch hier hat man ja die Möglichkeit, ein Icon zu setzen, wenn dies die Anforderung ist.

NACHTRAG: Eigendlich brauchst du dafür nicht mal ein JLabel. Eine eigene Klasse die den Text und das Icon zurückgibt dürfte da ausreichen.

Ach ja, das ist jetzt nur mal so ein Gedankenspiel von mir. Ob das funktioniert.. keine Ahnung, habe ich so noch nie ausprobiert.

MfG
hansmueller
 
Zuletzt bearbeitet:

Michael...

Top Contributor
Kenne das LaF nicht, aber das diese Effekte und die Darstellung können auch von ListUI des LaFs beeinflusst werden.
Was wird hier als Renderer genutzt? Wenn dieser von JLabel erbt, könnte man das Icon einfach draufsetzen oder eventell von genutzten Renderer erben...
 

hdi

Top Contributor
Okay danke, ich werd das dann mal so versuchen.

Wobei mir noch immer ein Rätsel ist wieso die getCellRenderer() Methode meiner JList scheinbar gar nicht den CellRenderer zurückliefert, der dafür benutzt wird.. Imho müsste mein allererster Ansatz (erstes Code-Bsp in meinem ersten Posting) ja genau diesen CellRenderer nutzen.

Aber mal sehn :D
 

Michael...

Top Contributor
Wobei mir noch immer ein Rätsel ist wieso die getCellRenderer() Methode meiner JList scheinbar gar nicht den CellRenderer zurückliefert, der dafür benutzt wird..
Das wird schon gemacht aber Dein letzter Renderer erbt von JPanel und implementiert nur ListCellRenderer. Zwar verbaust Du den Renderer des LaFs, aber damit wird Dein Renderer nicht automatisch zu einem SubstanceDefaultListCellRenderer.

Soweit ich das beim Überfliegen richtig gesehen habe, wird in der SubstanceListUI an unterschiedlichen Stellen geprüft, ob der Renderer eine Instanz von SubstanceDefaultListCellRenderer ist. Falls nicht werden Effekte wie MouseRollOver deaktiviert.
 

hdi

Top Contributor
edit:

So, nachdem ich mir jetzt nochmal den Source-Code angeschaut hab (Danke für die Links nochmal!) ist mir alles klar geworden:

Die SubstanceListUI, die ja bei meinem L&F verwendet wird, speichert sich das, was der CellRenderer als Component returned unter der Variablen "renderComponent" ab, und in der Methode die das ganze malen soll (paintCell() der ListUi) steht dreißterweise schon am Anfang:

Java:
 if (!(rendererComponent instanceof SubstanceDefaultListCellRenderer)) {
                  // if it's not Substance renderer - ask the Basic delegate to paint
                  // it.
                  super.paintCell(g, row, rowBounds, cellRenderer, dataModel,
                              selModel, leadIndex);
                  return;
            }

Was soll denn DAS?? Tut mir leid aber entweder die Leute von pushingpixels haben den Sinn eines Interfaces nicht verstanden oder sind einfach nur gemein? Das Interface sieht vor dass eine Component returned wird, und der ganze Code, der danach folgt mit den Leuchteffekten usw, ist überhaupt nicht an ein JLabel gebunden, würd genauso auch mit nem JPanel oder whatever funktionieren..

Das ist echt mal ne miese Nummer, und ich kann diese ListUI nicht nachprogrammieren und diese Zeile rauswerfen bzw die paintCell Methode überschreiben da die Hälfte der Ressourcen in packages versteckt sind, und für mich nicht nutzbar. Ich müsste das von scratch programmieren also gleich n eigenes L&F. Oder kucken ob das auch noch alles als Source Code verfügbar ist...

Meine letzte Hoffnung war jetzt halt das JLabel als JPanel zu vergewaltigen und ihm Dinge zu adden, geht ja. Aber wie ich schon befürchtet hab ignoriert er das schön...

Machen das alle L&F Programmierer nach dem Stil? Für mich sieht das echt einfahc nur so aus vonwegen "WEnn du unser L&F verwenden willst, dann bitte nur GENAU so wie wir es vorhatten, und keinerlei Anpassungen sind erlaubt, auch wenn sie möglich wären".

Ja sooooorry dass ich statt nem einfachen JLabel vllt ein JPanel mit zwei JLabels anzeigen will! Würd halt alles prima funktionieren wenn diese unsinnige Abfrage nicht drin wäre. BOAH wie mich das aufregt grad :(
 
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Swing Problem mit ListCellRenderer AWT, Swing, JavaFX & SWT 7
F ListCellRenderer mit JLabel und MouseListener AWT, Swing, JavaFX & SWT 4
B JList + ListCellRenderer AWT, Swing, JavaFX & SWT 5
hdi Swing ListCellRenderer + JTextArea + LineWrap AWT, Swing, JavaFX & SWT 6
frankred Swing Eigener ListCellRenderer D'n'D "MOVE" - Mauszeiger flackert AWT, Swing, JavaFX & SWT 14
H Swing ListCellRenderer einer JList zeichnet sporadisch falsch AWT, Swing, JavaFX & SWT 6
K Swing Schrift in Kopfzeile von JComboBox über ListCellRenderer ändern AWT, Swing, JavaFX & SWT 2
H JFormatterTextField und JButton in JList (ListCellRenderer) AWT, Swing, JavaFX & SWT 2
N JList (JXList) ListCellRenderer zur Laufzeit ändern (Anzeigefehler) AWT, Swing, JavaFX & SWT 6
GilbertGrape Kleinigkeit beim ListCellRenderer AWT, Swing, JavaFX & SWT 2
A ListCellRenderer und JScrollPane AWT, Swing, JavaFX & SWT 4
Tom299 JList ListCellRenderer wird überschrieben AWT, Swing, JavaFX & SWT 8
J problem mit ListCellRenderer und in der zeile ein Jbutton AWT, Swing, JavaFX & SWT 5
A JTabbedPane JList Listcellrenderer AWT, Swing, JavaFX & SWT 5
R JList + ListCellRenderer AWT, Swing, JavaFX & SWT 1
T LookAndFeel LookAndFeel funktioniert nicht beim JFrame wechsel AWT, Swing, JavaFX & SWT 3
F Setzen des LookAndFeel AWT, Swing, JavaFX & SWT 4
T LayoutManager LookAndFeel-Problem AWT, Swing, JavaFX & SWT 4
U LookAndFeel für eine Komponente AWT, Swing, JavaFX & SWT 2
N LookAndFeel Wie kann ich mein eigenes LookAndFeel machen? AWT, Swing, JavaFX & SWT 6
I LookAndFeel setzen AWT, Swing, JavaFX & SWT 17
I LookAndFeel AWT, Swing, JavaFX & SWT 15
GUI-Programmer Translucent JFrame mit System-LookAndFeel AWT, Swing, JavaFX & SWT 4
D LookAndFeel setzen AWT, Swing, JavaFX & SWT 2
K LookAndFeel LookAndFeel nur für einen Frame? AWT, Swing, JavaFX & SWT 6
B LookAndFeel für einen Komponenten AWT, Swing, JavaFX & SWT 2
J Swing LookAndFeel Klassenname herausfinden AWT, Swing, JavaFX & SWT 2
FuriKuri LookAndFeel in Linux setzen AWT, Swing, JavaFX & SWT 16
T Swing Substance LookAndFeel verhält sich merkwürdig AWT, Swing, JavaFX & SWT 4
G LookAndFeel AWT, Swing, JavaFX & SWT 5
G setLookAndFeel to default LookAndFeel? AWT, Swing, JavaFX & SWT 4
D LookAndFeel mit WindowBlinds AWT, Swing, JavaFX & SWT 2
DeeDee0815 LookAndFeel während der Laufzeit verstellen AWT, Swing, JavaFX & SWT 4
I LookAndFeel AWT, Swing, JavaFX & SWT 3
B Frage zu Synth LookAndFeel AWT, Swing, JavaFX & SWT 4
G Windows LookAndFeel - Classpath AWT, Swing, JavaFX & SWT 6
G Ändern der Standartschrift vom LookAndFeel AWT, Swing, JavaFX & SWT 4
G JButton LookAndFeel AWT, Swing, JavaFX & SWT 2
O LookAndFeel und Performance AWT, Swing, JavaFX & SWT 7
M Problem mit LookAndFeel auf unterschiedlichen Rechnern AWT, Swing, JavaFX & SWT 3
B XP-LookAndFeel + modifizierter JTableHeader unsichtbar AWT, Swing, JavaFX & SWT 3
M LookAndFeel? Erst beim 2.Mal Öffnen eines Menüs? AWT, Swing, JavaFX & SWT 3
T LookAndFeel Erstellung :: Problem mit JTabbedPanes AWT, Swing, JavaFX & SWT 2
D Font eines JLabels verändern, JLabel mit LookAndFeel-Format AWT, Swing, JavaFX & SWT 2
N LookAndFeel - Nicht gleich alles überschreiben AWT, Swing, JavaFX & SWT 8
G JFileChooser: leeres Fenster nach LookAndFeel-Wechel AWT, Swing, JavaFX & SWT 7
M LookAndFeel und Mnemonische Kürzel AWT, Swing, JavaFX & SWT 7
G LookAndFeel in extra Fenster einstellbar AWT, Swing, JavaFX & SWT 2
B wie behält man die aktuellen LookAndFeel einstellungen? AWT, Swing, JavaFX & SWT 7

Ähnliche Java Themen

Neue Themen


Oben