# JPanel in JTable einfügen



## pausch (6. Sep 2011)

Hallo,

Ich bin dabei ein MediaManagement Programm zu bauen und bin jetzt bei einer Übersichtsliste angegekommen. Da die gelisteten Inhalte auch bewertet werden können sollen, macht es Sinn in diese Tabelle ein JPanel hinzuzufügen in dem ich dann 5 Sternchen hinzufügen kann, die ich mit einem MouseListener belege, die dann halt die Bewertung des Inhaltes setzen. 
Problem: Wie bekomme ich jetzt ein JPanel in ein JTable?!

Danke für eure Mühe...

pausch


----------



## bERt0r (6. Sep 2011)

Ich glaube da kann dir das weiterhelfen: How to Use Tables - Using Custom Renderers


----------



## Michael... (6. Sep 2011)

pausch hat gesagt.:


> Wie bekomme ich jetzt ein JPanel in ein JTable?!


Ein JPanel in eine JTable bzw. deren Model zu stecken macht eigentlich keinen Sinn und untergräbt das bei der JTable verwendete Rendering Konzept:
Die Zellen einer JTable werden mit einigen wenigen Rendererkomponenten (default nur ein einziges JLabel) dargestellt.
bERt0r hat ja bereits einen Link zu dem Thema gepostet. Hier in den FAQs gibt's es auch ein umfangreiches Tutorial zur JTable - finde allerdings grad den Link nicht. Vielleicht hat ja jemand anderes diesen zur Hand.

#EDIT:
gefunden:http://www.java-forum.org/bilder-gui-damit-zusammenhaengt/4841-jtable-ubersicht-teil-1-teil-8-a.html#post23457


----------



## pausch (6. Sep 2011)

Michael... hat gesagt.:


> #EDIT:
> gefunden:http://www.java-forum.org/bilder-gui-damit-zusammenhaengt/4841-jtable-ubersicht-teil-1-teil-8-a.html#post23457



Danke für den Link, aber ganz untätig war ich ja auch nicht und habe das Tutorial auch schon gefunden... Aber explizit für mein Problem habe ich da nichts passendes gefunden bisher. Vielleich war ich auch zu voreilig und habe es übersehen...
Ich sitze jetzt gerade an einem [japi]TableCellRenderer[/japi]. Die Methode 

```
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
```
 muss hier ja überschrieben werden. Als [japi]Component[/japi] der da zurückgegeben wird benutze ich halt ein JPanel mit meinen Bewertungs-Sternchen drin.

Oder hast du eine Bessere Idee?

Danke nochmal für eure Mühe...


----------



## hdi (6. Sep 2011)

Ist schon richtig, wie du das machst. Beachte allerdings, was Michael gesagt hat: Die JTable ist eigentlich nicht dafür entworfen, komplexere Komponenten als Zellen zu haben. Es kann da schnell zu Performance-Problemen kommen, da die Zellen u.U. sehr oft gezeichnet werden. Ich weiß das weil ich genau das selbe auch mal gemacht hab (selbe Software, nur waren's bei mir keine Sterchnen sondern eine bunte Bar).

Es gibt dafür allerdings eine Lösung, und zwar musst du gewisse Methoden für das Repaint überschreiben, und dabei leer implementieren - sie sind nicht immer nötig und boosten die Performance in so einem Fall.

D.h. am besten du machst deinen TableRenderer gleich mal *extends JPanel*. D.h. du returnest in der Methode "this". Ansonsten müsstest du in der Methode halt eine anonyme Klasse verwenden. Auf jeden Fall musst du die Methoden überschreiben.. Wenn ich jetzt wüsste welche genau das waren.. Ich such mal ein bisschen in meinen alten Threads, vllt finde ich es.

Aber wie gesagt, vom Prinzip schon korrekt was du tust.


----------



## pausch (6. Sep 2011)

Das mit dem Erben vom JPanel habe ich mir schon gedacht und ist schon so implementiert danke


----------



## hdi (6. Sep 2011)

Here you go:


```
// The following methods override the defaults for performance reasons
    public void validate() {}
    public void revalidate() {}
    protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {}
    public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {}
```

Und  hier findest du noch meine App. Ist leider kein Source Code drin, und ich hab den auch nicht mehr. Ist auch nich unbedingt professionell gemacht.. Aber wenn du etwas ähnliches implementieren willst und nicht weißt wie, schick mir einfach ne PN, vllt kann ich helfen

PS: Beim Start legt das Programm eine Datei oder einen Ordner in deinem Home-Verzeichnis an. Glaubi ch zumindest  Oder in dem Verzeichnis, in dem die jar liegt. Dort werden die Filme gespeichert. Also lösch das am besten auch wieder wenn du die Software in den Mülleimer schiebst.


----------



## pausch (6. Sep 2011)

...wie füge ich denn jetzt meinen TableCellRenderer meiner Tabelle hinzu???


```
try {
			DVD[] dvds = DAOFactory.getDVDDao().readAllDVD();
			String[][] rowData = new String[dvds.length][4];
			for(int i=0; i<rowData.length; i++){
				rowData[i][0] = dvds[i].getTitle();
				rowData[i][1] = new Integer(dvds[i].getDauer()).toString();
				rowData[i][2] = new Integer(dvds[i].getJahr()).toString();
			}
			String[] columns = {"Titel", "Bewertung", "Dauer", "Jahr"};
			uebersichtTable = new JTable(rowData, columns);
			TableColumn bewertungsColumn = uebersichtTable.getColumn(1);
			for(int i=0; i<rowData.length; i++){
				bewertungsColumn.setCellRenderer(new BewertungTableCellRenderer());
			}
			add(new JScrollPane(uebersichtTable), gbc);
		} catch (SQLException e) {
			logger.error(e);
			RootController.setException(e);
		}
```

Der bewirft mich mit einer [japi]IllegalArgumentException [/japi]in der Zeile wo ich mir die TableColumn hole... Da die Methode ein [japi]Object[/japi] erwartet, habe ich das auch schon mit "Bewertung" versuche, aber dann kommt (berechtigter weise) eine ClassCastException: java.lang.String cannot be cast to java.lang.Integer.

Ich glaube ich bin zu doof für JTables^^

Aber danke für eure Unterstützung


----------



## hdi (7. Sep 2011)

Also erstmal macht man das nicht in einer Schleife. Du setzt den Renderer nur *ein mal*. Du machst ja bei jedem Schleifendurchlauf das selbe 



> Der bewirft mich mit einer IllegalArgumentException in der Zeile wo ich mir die TableColumn hole...


Hm kann ich grad nicht glauben.. Die Table hat 4 Spalten, getColumn(1) dürfte keine IAE werfen.. Sicher, dass das die richtige Zeile ist? Poste mal den Stack-Trace


----------



## andiv (7. Sep 2011)

Ich verwende normalerweise nicht setCellRenderer sondern direkt auf der JTable setDefaultRenderer und übergebe die Klasse, die die Objekte in der gewünschten Spalte haben.


----------



## pausch (7. Sep 2011)

*Hust* die schleife war unüberlegt^^
Danke für den Hinweis... Jetzt der StackTrace: 

```
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Identifier not found
	at javax.swing.table.DefaultTableColumnModel.getColumnIndex(DefaultTableColumnModel.java:282)
	at javax.swing.JTable.getColumn(JTable.java:2553)
	at de.schaefer.mediaManagement.ui.general.UebersichtView.<init>(UebersichtView.java:52)
	at de.schaefer.mediaManagement.control.viewcontroller.UebersichtController.<init>(UebersichtController.java:14)
	at de.schaefer.mediaManagement.control.viewcontroller.HomeController.uebersicht(HomeController.java:31)
	at de.schaefer.mediaManagement.ui.general.HomeView$1.actionPerformed(HomeView.java:79)
	at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2012)
	at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2335)
	at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:404)
	at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:253)
	at java.awt.Component.processMouseEvent(Component.java:6268)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
	at java.awt.Component.processEvent(Component.java:6033)
	at java.awt.Container.processEvent(Container.java:2045)
	at java.awt.Component.dispatchEventImpl(Component.java:4629)
	at java.awt.Container.dispatchEventImpl(Container.java:2103)
	at java.awt.Component.dispatchEvent(Component.java:4455)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4633)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4297)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4227)
	at java.awt.Container.dispatchEventImpl(Container.java:2089)
	at java.awt.Window.dispatchEventImpl(Window.java:2517)
	at java.awt.Component.dispatchEvent(Component.java:4455)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:649)
	at java.awt.EventQueue.access$000(EventQueue.java:96)
	at java.awt.EventQueue$1.run(EventQueue.java:608)
	at java.awt.EventQueue$1.run(EventQueue.java:606)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:116)
	at java.awt.EventQueue$2.run(EventQueue.java:622)
	at java.awt.EventQueue$2.run(EventQueue.java:620)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:619)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)
```


----------



## pausch (7. Sep 2011)

andiv hat gesagt.:


> Ich verwende normalerweise nicht setCellRenderer sondern direkt auf der JTable setDefaultRenderer und übergebe die Klasse, die die Objekte in der gewünschten Spalte haben.



Aber dann würde ja der CellRenderer für alle Zellen angewandt werden. Ich möchte den aber doch nur auf eine Spalte anwenden, um in den anderen Spalten meine anderen Werte anzeigen zu lassen, wie den Titel der DVD oder die Länge, das Jahr etc.

Warum einfach wenn es auch kompliziert geht ^^


----------



## hdi (7. Sep 2011)

Ach ok, die Methode erwartet gar keinen Index, sondern einen Identifiert:
JTable (Java Platform SE 7 ))

Wahrscheinlich ist der Identifiert der Spalten-Name.

Ansonten mach es über 
	
	
	
	





```
getColumnModel().getColumn(1);
```


----------



## pausch (7. Sep 2011)

Auch das habe ich versucht, aber wie vorhin geschrieben fliegt dann eine:

```
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
	at de.schaefer.mediaManagement.ui.general.BewertungTableCellRenderer.getTableCellRendererComponent(BewertungTableCellRenderer.java:69)
	at javax.swing.JTable.prepareRenderer(JTable.java:5736)
	at javax.swing.plaf.synth.SynthTableUI.paintCell(SynthTableUI.java:636)
	at javax.swing.plaf.synth.SynthTableUI.paintCells(SynthTableUI.java:533)
	at javax.swing.plaf.synth.SynthTableUI.paint(SynthTableUI.java:322)
	at javax.swing.plaf.synth.SynthTableUI.update(SynthTableUI.java:251)
	at javax.swing.JComponent.paintComponent(JComponent.java:765)
	at javax.swing.JComponent.paint(JComponent.java:1029)
	at javax.swing.JComponent.paintChildren(JComponent.java:866)
	at javax.swing.JComponent.paint(JComponent.java:1038)
	at javax.swing.JViewport.paint(JViewport.java:764)
	at javax.swing.JComponent.paintChildren(JComponent.java:866)
	at javax.swing.JComponent.paint(JComponent.java:1038)
	at javax.swing.JComponent.paintChildren(JComponent.java:866)
	at javax.swing.JComponent.paint(JComponent.java:1038)
	at javax.swing.JComponent.paintToOffscreen(JComponent.java:5138)
	at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:302)
	at javax.swing.RepaintManager.paint(RepaintManager.java:1188)
	at javax.swing.JComponent._paintImmediately(JComponent.java:5086)
	at javax.swing.JComponent.paintImmediately(JComponent.java:4896)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:783)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:735)
	at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:677)
	at javax.swing.RepaintManager.access$700(RepaintManager.java:58)
	at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1593)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:226)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:647)
	at java.awt.EventQueue.access$000(EventQueue.java:96)
	at java.awt.EventQueue$1.run(EventQueue.java:608)
	at java.awt.EventQueue$1.run(EventQueue.java:606)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:617)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
	at de.schaefer.mediaManagement.ui.general.BewertungTableCellRenderer.getTableCellRendererComponent(BewertungTableCellRenderer.java:69)
	at javax.swing.JTable.prepareRenderer(JTable.java:5736)
	at javax.swing.plaf.synth.SynthTableUI.paintCell(SynthTableUI.java:636)
	at javax.swing.plaf.synth.SynthTableUI.paintCells(SynthTableUI.java:533)
	at javax.swing.plaf.synth.SynthTableUI.paint(SynthTableUI.java:322)
	at javax.swing.plaf.synth.SynthTableUI.update(SynthTableUI.java:251)
	at javax.swing.JComponent.paintComponent(JComponent.java:765)
	at javax.swing.JComponent.paint(JComponent.java:1029)
	at javax.swing.JComponent.paintChildren(JComponent.java:866)
	at javax.swing.JComponent.paint(JComponent.java:1038)
	at javax.swing.JViewport.paint(JViewport.java:764)
	at javax.swing.JComponent.paintChildren(JComponent.java:866)
	at javax.swing.JComponent.paint(JComponent.java:1038)
	at javax.swing.JComponent.paintChildren(JComponent.java:866)
	at javax.swing.JComponent.paint(JComponent.java:1038)
	at javax.swing.JComponent.paintChildren(JComponent.java:866)
	at javax.swing.JComponent.paint(JComponent.java:1038)
	at javax.swing.JComponent.paintChildren(JComponent.java:866)
	at javax.swing.JComponent.paint(JComponent.java:1038)
	at javax.swing.JLayeredPane.paint(JLayeredPane.java:581)
	at javax.swing.JComponent.paintChildren(JComponent.java:866)
	at javax.swing.JComponent.paintToOffscreen(JComponent.java:5145)
	at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:302)
	at javax.swing.RepaintManager.paint(RepaintManager.java:1188)
	at javax.swing.JComponent.paint(JComponent.java:1015)
	at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39)
	at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:78)
	at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:115)
	at java.awt.Container.paint(Container.java:1784)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:794)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:735)
	at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:677)
	at javax.swing.RepaintManager.access$700(RepaintManager.java:58)
	at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1593)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:226)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:647)
	at java.awt.EventQueue.access$000(EventQueue.java:96)
	at java.awt.EventQueue$1.run(EventQueue.java:608)
	at java.awt.EventQueue$1.run(EventQueue.java:606)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:617)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)
```

EDIT:
Mit dem Umweg über das Model läufts, jetzt hat nur noch mein CellRenderer Feher, aber die sind morgen dran 
Danke für deine Hilfe, ich schreib dir mal PNs bei Problemen 

jetzt siehts folgendermaßen aus: 
	
	
	
	





```
try {
			DVD[] dvds = DAOFactory.getDVDDao().readAllDVD();
			String[][] rowData = new String[dvds.length][4];
			for (int i = 0; i < rowData.length; i++) {
				rowData[i][0] = dvds[i].getTitle();
				rowData[i][1] = new Integer(dvds[i].getDauer()).toString();
				rowData[i][2] = new Integer(dvds[i].getJahr()).toString();
			}
			String[] columns = { "Titel", "Bewertung", "Dauer", "Jahr" };
			uebersichtTable = new JTable(rowData, columns);
			TableColumn bewertungsColumn = uebersichtTable
					.getColumnModel().getColumn(1);
			bewertungsColumn.setCellRenderer(new BewertungTableCellRenderer());
			add(new JScrollPane(uebersichtTable), gbc);
		} catch (SQLException e) {
			logger.error("DVDs konnten nicht abgefragt werden", e);
			RootController.setException(e);
		}
```

damit auch andere aus meinen Fehlern lernen können.

Grüße
pausch


----------



## hdi (7. Sep 2011)

Das liegt jetzt aber an deinem Renderer: BewertungTableCellRenderer.java:*69*

Anscheinend castest du da irgendwas falsch.. Zeig mal die Methode getTableCellRendererComponent


----------



## pausch (8. Sep 2011)

CellRenderer ist jetzt geschrieben aber tut nicht das was er soll 

...hier der Code: 

```
package de.schaefer.mediaManagement.ui.general;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;

public class BewertungTableCellRenderer extends JPanel implements
		TableCellRenderer {

	/**
	 * 
	 */
	private static final long serialVersionUID = -7417093007447000853L;

	@Override
	public Component getTableCellRendererComponent(JTable table, Object value,
			boolean isSelected, boolean hasFocus, int row, int column) {
		int val = 0;
		if (value instanceof String) {
			val = Integer.parseInt(value.toString());
		} else if (value instanceof Integer) {
			val = (Integer) value;
		}
		if (val <= 5 && val > 0) {
			JButton[] grau = new JButton[5-val];
			JButton[] farbig = new JButton[val];
			for(int i=0; i<farbig.length; i++){
				farbig[i] = new JButton(new ImageIcon("sternFarbig.png"));
				farbig[i].setPreferredSize(new Dimension(20, 30));
				this.add(farbig[i]);
			}
			for(int i=0; i<grau.length; i++){
				grau[i] = new JButton(new ImageIcon("sternGrau.png"));
				grau[i].setPreferredSize(new Dimension(20, 30));
				this.add(grau[i]);
			}
			return this;
		}
		return new JPanel();
	}
}
```

Und das was dabei rauskommt seht ihr im Anhang. Es werden alle JPanels in jeder (!!) zeile angezeigt 

Achja: folgendermaßen füge ich den TableCellRenderer der Tabelle hinzu:


```
public UebersichtView(UebersichtController uc) {
		super();
		this.uc = uc;
		setLayout(new GridBagLayout());

		GridBagConstraints gbc = new GridBagConstraints();
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.anchor = GridBagConstraints.CENTER;
		gbc.insets = new Insets(10, 0, 10, 0);
		try {
			DVD[] dvds = DAOFactory.getDVDDao().readAllDVD();
			Object[][] rowData = new Object[dvds.length][4];
			for (int i = 0; i < rowData.length; i++) {
				rowData[i][0] = dvds[i].getTitle();
				rowData[i][1] = new Integer(dvds[i].getBewertung());
				rowData[i][2] = new Integer(dvds[i].getDauer());
				rowData[i][3] = new Integer(dvds[i].getJahr());
			}
			String[] columns = { "Titel", "Bewertung", "Dauer", "Jahr" };
			uebersichtTable = new JTable(rowData, columns);
			uebersichtTable.setRowHeight(40);
			TableColumn bewertungsColumn = uebersichtTable.getColumn("Bewertung");
			bewertungsColumn.setCellRenderer(new BewertungTableCellRenderer());
			add(new JScrollPane(uebersichtTable), gbc);
		} catch (SQLException e) {
			logger.error("DVDs konnten nicht abgefragt werden", e);
			RootController.setException(e);
		}

		repaint();
	}
```


EDIT: 
Zum allgemeinen Verständnis: Die erste DVD hat 3 Sterne und alle folgenden nur einen, deshalb meine Vermutung, dass alle JPanels hintereinander gehängt werden.


----------



## pausch (8. Sep 2011)

*Hust* wofür ein removeAll() doch alles gut ist...


----------



## pausch (8. Sep 2011)

Nächste Frage, die ich mir jetzt wirklich nicht selbst beantworten kann:

Wie bekomme ich die folgenden ActionListener auf den Buttons ausgeführt? Wenn ich in die Tabelle klicke, passiert gar nichts 


```
package de.schaefer.mediaManagement.ui.general;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;

public class BewertungTableCellRenderer extends JPanel implements
		TableCellRenderer {

	/**
	 * 
	 */
	private static final long serialVersionUID = -7417093007447000853L;

	@Override
	public Component getTableCellRendererComponent(final JTable table, Object value,
			final boolean isSelected, final boolean hasFocus, final int row, final int column) {
		this.removeAll();
		final int val;
		if (value instanceof String) {
			val = Integer.parseInt(value.toString());
		} else if (value instanceof Integer) {
			val = (Integer) value;
		} else {
			val = -1;
		}
		if (val <= 5 && val > 0) {
			JButton[] grau = new JButton[5-val];
			JButton[] farbig = new JButton[val];
			for(int i=0; i<farbig.length; i++){
				farbig[i] = new JButton(new ImageIcon("sternFarbig.png"));
				farbig[i].setPreferredSize(new Dimension(20, 30));
				farbig[i].addActionListener(new ActionListener(){
					public void actionPerformed(ActionEvent ae){
						getTableCellRendererComponent(table, val-1, isSelected, hasFocus, row, column);
					}
				});
				this.add(farbig[i]);
			}
			for(int i=0; i<grau.length; i++){
				grau[i] = new JButton(new ImageIcon("sternGrau.png"));
				grau[i].setPreferredSize(new Dimension(20, 30));
				grau[i].addActionListener(new ActionListener(){
					public void actionPerformed(ActionEvent ae){
						getTableCellRendererComponent(table, val+1, isSelected, hasFocus, row, column);
					}
				});
				this.add(grau[i]);
			}
			return this;
		}
		return new JPanel();
	}
}
```

Anbindung an die JTable wie oben schon gepostet...

Nebenbei wäre es für den CellEditor noch relativ Sinnvoll zu wissen, um welche DVD er sich grade kümmert um die Bewertungs-Änderungen auch in die Datenbank übermitteln zu können. Sonst kann man ja froh editieren und nichts geschieht im backend...


----------



## Michael... (8. Sep 2011)

Tipp: Ein Renderer rendert nur ;-)
Zum Editieren verwendet JTable TableCellEditor der prinzipiell ähnlich funktioniert wie ein Renderer nur ein paar Methoden hat.

Um sich nicht mit dem Editor rumschlagen zu müssen, könnte man auch einfach mit einem MouseListener an der JTable arbeiten -  man hätte halt nicht diesen Button gerückt und rollover Effekt.


----------



## pausch (8. Sep 2011)

Hättest du ein Beispiel für "nur mit dem Mouselistener am Table arbeiten"? Ich kann mir da grade nciht viel drunter vorstellen...


----------



## Michael... (8. Sep 2011)

beispiel gerade nicht zur Hand, sollten sich aber sicher hier oder im Netz ein paar finden lassen.
Einfach MouseListener an der JTable registrieren, in der mouseClicked(...) anhand des Points des MouseEvents Zeilen- und Spaltenindex bestimmen (JTable bietet dazu jeweils eine Methode an row/columnAtPoint oder so ähnlich) und schon ist man genauso weit wie im CellEditor.


----------



## pausch (8. Sep 2011)

Das letzte problem(chen?) was mich noch plagt ist, dass der BewertungCellEditor jetzt noch wissen muss welche DVD er editert.

Wie lässt sich das jetzt lösen? Ich füge ja einer ganzen Spalte diesen Editor an...


```
try {
			DVD[] dvds = DAOFactory.getDVDDao().readAllDVD();
			Object[][] rowData = new Object[dvds.length][4];
			for (int i = 0; i < rowData.length; i++) {
				rowData[i][0] = dvds[i].getTitle();
				rowData[i][1] = new Integer(dvds[i].getBewertung());
				rowData[i][2] = new Integer(dvds[i].getDauer());
				rowData[i][3] = new Integer(dvds[i].getJahr());
			}
			String[] columns = { "Titel", "Bewertung", "Dauer", "Jahr" };
			uebersichtTable = new JTable(rowData, columns);
			uebersichtTable.setRowHeight(40);
			TableColumn bewertungsColumn = uebersichtTable.getColumn("Bewertung");
			bewertungsColumn.setCellEditor(new BewertungCellEditor());
			bewertungsColumn.setCellRenderer(new BewertungTableCellRenderer());
			add(new JScrollPane(uebersichtTable), gbc);
		} catch (SQLException e) {
			logger.error("DVDs konnten nicht abgefragt werden", e);
			RootController.setException(e);
		}

		repaint();
```


```
package de.schaefer.mediaManagement.ui.general;

import java.awt.Component;
import java.awt.Dimension;

import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;

public class BewertungTableCellRenderer extends JPanel implements
		TableCellRenderer {

	/**
	 * 
	 */
	private static final long serialVersionUID = -7417093007447000853L;
	SternButton[] sterne = new SternButton[5];

	@Override
	public Component getTableCellRendererComponent(final JTable table,
			Object value, final boolean isSelected, final boolean hasFocus,
			final int row, final int column) {
		final int val;
		if (value instanceof String) {
			val = Integer.parseInt(value.toString());
		} else if (value instanceof Integer) {
			val = (Integer) value;
		} else {
			val = -1;
		}
		if (val <= 5 && val > 0) {
			removeAll();
			int i = 0;
			for (; i < 5; i++) {
				if (i < val)
					sterne[i] = new SternButton(i + 1, true);
				else
					sterne[i] = new SternButton(i + 1, false);
				sterne[i].setPreferredSize(new Dimension(20, 30));
				this.add(sterne[i]);
			}

		}
		return this;
	}
}
```


```
package de.schaefer.mediaManagement.ui.general;

import javax.swing.ImageIcon;
import javax.swing.JButton;

public class SternButton extends JButton {

	/**
	 * 
	 */
	private static final long serialVersionUID = -2526897634970878854L;
	int nr;
	boolean farbig;
	
	public SternButton(int zahl, boolean farbig){
		if(farbig){
			setIcon(new ImageIcon("sternFarbig.png"));
		} else {
			setIcon(new ImageIcon("sternGrau.png"));
		}
		nr = zahl;
	}
	
	public int getNr(){
		return nr;
	}
}
```


----------



## Michael... (8. Sep 2011)

pausch hat gesagt.:


> Das letzte problem(chen?) was mich noch plagt ist, dass der BewertungCellEditor jetzt noch wissen muss welche DVD er editert.


Das gleiche Problem wird hier in dem Post diskutiert:
http://www.java-forum.org/awt-swing-swt/123976-komplette-objekte-jtable-einfuegen.html#post802628
Man könnte ein eigenes TableModel schreiben in dem man nur eine Liste mit den DVDs hält und entsprechend die set/getValueAt(...) entsprechend überschreibt. In einer oder der benötigten Spalte gibt man das komplette DVD Objekt zurück - war wohl ein eher pragmatischer Ansatz und man müsste den CellRenderer der Spalte entsprechend anpassen.


----------



## pausch (8. Sep 2011)

Ich habs jetzt geschafft. Danke für eure Hilfe!! 

Grüße
pausch


----------

