Swing TableCellRenderer: setText() vs. setIcon()

Curry

Aktives Mitglied
Hallo!

Ich habe einen TableCellRenderer geschrieben, der ein Icon in einer Tabelle anzeigen soll. Wenn es die Bilddatei zu dem Icon jedoch nicht gibt, dann soll der Wert der Zelle als Text angezeigt werden.

Doch, wenn das Bild zu einem bestimmten Text nicht vorhanden ist, dann wird dieser Text in jeder Zeile dieser Spalte neben dem Icon angezeigt. Und in den Zeilen, in denen eigentlich nur der Text angezeigt werden sollte, wird irgendein anderes Icon zusammen mit dem eigentlichen Text angezeigt.

Hat jemand eine Idee?

Java:
public class PositionCellRenderer extends JLabel implements TableCellRenderer {

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

		this.setOpaque(true);

		File f = new File("d:/test/pics/position/pos" + value.toString() + ".png");

		if(f.isFile()) {
			ImageIcon icon = new ImageIcon("d:/test/pics/position/pos" + value.toString() + ".png");
			setIcon(  icon );
		}
		else {
			setText( value.toString() );
		}

		if (isSelected) {
			setForeground( new Color(255, 255, 255) );
			setBackground( new Color(90,130,40) );
		}
		else {
			setForeground( new Color(255, 255, 255) );

			if(row % 2 > 0) {
				if(column % 2 > 0) {
					setBackground(new Color(50,90,20));
				}
				else {
					setBackground(new Color(60,100,30));
				}
			}
			else {
				if(column % 2 > 0) {
					setBackground(new Color(30,70,10));
				}
				else {
					setBackground(new Color(40,80,20));
				}
			}

		}
		return this;
	}
}
 
Wenn ich mich jetzt nicht täusche:

du legst immer eine Datei an

Java:
File f = new File("d:/test/pics/position/pos" + value.toString() + ".png");

Damit kommst du doch nie in den else-Zweig. Was du machen willst ist doch nur ein icon aus einer vorher schon bestehenden Datei laden, oder?

Ich hab das so gemacht:

Java:
URL fileUrl = getClass().getResource(DATEINAME);
ImageIcon icon;

if(fileUrl != null ) {
      ico = new ImageIcon(fileUrl);
}
 
Was du machen willst ist doch nur ein icon aus einer vorher schon bestehenden Datei laden, oder?
Genau das möchte ich machen und für den Fall, dass es ein Bild nicht gibt, soll er den Text anzeigen.

Wenn ich es so mache, dann wird immer der else-Zweig genommen und der Wert als Text angezeigt.

Java:
URL fileUrl = getClass().getResource("d:/test/pics/position/pos" + value.toString() + ".png");
		ImageIcon icon;

		if(fileUrl != null ) {
			icon = new ImageIcon(fileUrl);
		}
		else {
			setText( value.toString() );
		}
 
Dein Pfad stimmt nicht. Mit getClass().getResource() verwendest du den relativen Pfad deiner Klasse. Liegt deine Datei genau in dem Ordner, wo du auch deine Source-Datei der Klasse liegt reicht z.b. "pos" + value.toString() + ".png" . (Evtl. auch mit / davor).

Vergiss nicht auch das icon zu setzen.

Ansonsten nimm mal bei deinem ursprünglichen Code anstatt .isFile() .exists()
 
Zuletzt bearbeitet:
Wenn Du den ersten Code nimmst, musst Du natürlich die Renderer Komponente immer in den Zustand versetzen den Du benötigtst - bedenke, dass immer wieder die selbe Komponten zum Zeichnen der Zelle verwendet wird. Wenn in der Zelle zuvor ein Icon gesetzt wurde und in der Zelle danach keines gesetzt werden soll, musst Du das bisherige Icon wieder entfernen.
Java:
if(f.isFile()) {
            ImageIcon icon = new ImageIcon("d:/test/pics/position/pos" + value.toString() + ".png");
            setIcon(  icon );
            setText("");
}
else {
            setIcon(null);
            setText( value.toString() );
}
Ansonsten in der Renderermethode nicht dauernd neue Objekte erzeugen, d.h. alle benötigten Bilder einmal bei der Initialisierung des Renderers laden, genauso das erzeugen der Farb Objekte.
Die String-Icon-Zuordnung kann man in einer Map speichern, oder man verwendet direkt eigene Objekte im TableModel.
 
Vielen Dank für die wertvollen Erläuterungen und Tipps!

Jetzt funktioniert es sehr schön und ich habe auch die Sache mit der initialisierung der Variablen umgestellt.

Hattest du es so gemeint?

Nun schaut es so aus:
Java:
public class PositionCellRenderer extends JLabel implements TableCellRenderer {

	private Color colorEvenEven		= new Color(40,80,20);
	private Color colorEvenUneven	= new Color(30,70,10);

	private Color colorUnevenEven	= new Color(60,100,30);
	private Color colorUnevenUneven = new Color(50,90,20);

	private Color colorForeground	= new Color(255, 255, 255);

	private Color colorSelected		= new Color(90,130,40);

	private HashMap<Integer, ImageIcon> icons;
	private int s = 0;
	private int n = 0;

	/**
	 * Der Konstruktor des CellRenderers wird nur einmal für alle Zellen aufgerufen. 
	 */
	public PositionCellRenderer() {
		s++;
		System.out.println("start = " + s);

		icons = new HashMap<Integer, ImageIcon>();

		File dir = new File("d:/test/pics/position/");
		File[] files = dir.listFiles();

		if (files != null) {
			for (int i = 0; i < files.length; i++) {
				if (files[i].isFile() && files[i].getName().startsWith("pos")) {
					String filename		= files[i].getName();
					String substring	= filename.substring(3, filename.length() - 4);
					icons.put(Integer.parseInt(substring), new ImageIcon( files[i].getAbsolutePath() ));
				}
			}
		}
	}

	/*
	 * Da es für alle Zellen in der Tabelle, für die dieser CellRenderer definiert wurde, nur ein Objekt dieses CellRenderers gibt,
	 * wird diese Methode immer in demselben Objekt aufgerufen.
	 */
	public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

		n++;
		System.out.println("getTableCellRendererComponent -> " + n + " -> " + row + " / " + column + " -> " + isSelected);
		
		this.setOpaque(true);
		this.setHorizontalAlignment(JLabel.CENTER);

		if(icons.containsKey( (Integer) value )) {
			setIcon( icons.get( (Integer) value ) );
			setText( "" );
		}
		else {
			setIcon( null );
			setText( value.toString() );
		}

		if (isSelected) {
			setForeground( colorForeground );
			setBackground( colorSelected );
		}
		else {
			setForeground( colorForeground );

			if(row % 2 > 0) {
				if(column % 2 > 0) {
					setBackground( colorUnevenUneven );
				}
				else {
					setBackground( colorUnevenEven );
				}
			}
			else {
				if(column % 2 > 0) {
					setBackground( colorEvenUneven );
				}
				else {
					setBackground( colorEvenEven );
				}
			}

		}
		return this;
	}
}
 

Zurück
Oben