Objekte grafisch darstellen

Hallo,

bin gerade dabei ein programm zu erweitern und dazu möchte ich gerne eine liste erstellen, in dieser sollen objekte angezeigt werden. jetzt allerdings nicht nur als einzeiler sondern da einige informationen zu diesen objekten gehören dachte ich da an so ein art rechteck das mehrere zeilen hat.

so etwa wie im bild nur muss es keine icons enthalten, aber buttons zum entfernen wären auch nicht schlecht.

jetzt hab ich allerdings leider kein blassen schimmer wie ich das anstellen kann :frowning:

dachte da an rechtecke zeichnen lassen und diese mit text zu versehen wäre das eine möglichkeit?

oder gibt es da eine swing komponente die ich übersehen hab?

zweite idee wäre es jpanels einzufügen die dann eben zwei, drei labels enthalten und dann noch buttons.

könnte man diese jpanels in einer jlist abspeichern so das ich mich nicht um die position kümmern muss?

mfg

tommy

ich würde eine eigene Implementierung des [japi]ListCellRenderer[/japi] empfehlen.

bye
TT

ich muss dann aber schon ein jpanel zurück geben?

also


blablabbla

}```

ja, aber nicht davon erben…

bye
TT

ok erstmal danke für den ansatz werde mich morgen dran versuchen

wirf auch einen Blick auf die default-Implementierung.

bye
TT

Wenn du Buttons in deiner Liste haben willst wird das mit dem ListCellRenderer nicht funktionieren. Am besten du schreibst dir eine Klasse die von JPanel erbt und eine View für einen deiner Listeneinträge repräsentiert. Für jeden Eintrag erstellst du jetzt eine solche Klasse und packst die in ein Vertikales Layout (z.B Box)

habe mich entschlossen die buttons weg zu lassen.

mein objekt welches die daten enthält erbt nun von einem JPanel,

wenn ich diese objekte nun in die liste einfüge habe ich das problem das diese alle oben hängen und mein renderer wird nicht auf gerufen

Objekt welches der liste hinzugefügt wird:


	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String oid = "";
	private String value = "";
	private int step = 0;
	private final JLabel oidlbl, valuelbl, stepid;
	private final Font font = new Font("Tahoma", Font.PLAIN, 14);
	private final Font stepfont = new Font("Tahoma", Font.PLAIN, 30);

	public Step(String oid) {
		this.oid = oid;
		setLayout(null);
		this.setBackground(Color.WHITE);
		this.setSize(310, 58);
		oidlbl = new JLabel("OID: " + oid);
		oidlbl.setFont(font);
		oidlbl.setBounds(60, 10, 200, 14);
		add(oidlbl);
		valuelbl = new JLabel("value: " + value);
		valuelbl.setBounds(60, 34, 200, 14);
		valuelbl.setFont(font);
		add(valuelbl);
		stepid = new JLabel(String.valueOf(step));
		stepid.setBounds(5, 9, 40, 38);
		stepid.setFont(stepfont);
		add(stepid);
		this.setOpaque(true);
	}

	public int getStep() {
		return step;
	}

	public void setStep(int step) {
		this.step = step;
	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}

	public String getOid() {
		return oid;
	}

	public void setOid(String oid) {
		this.oid = oid;
	}

}```

listen aufruf:

```JList<Step> list = new JList<Step>();
		list.setCellRenderer(new FWListRenderer());
		scrollPane2.setViewportView(list);
		list.add(new Step("1.3.3.3.3.3."));
		list.add(new Step("1.3.3.3.3.3."));
		list.add(new Step("1.3.3.3.3.3."));
		list.add(new Step("1.3.3.3.3.3."));
		list.add(new Step("1.3.3.3.3.3."));
		list.add(new Step("1.3.3.3.3.3."));
		list.add(new Step("1.3.3.3.3.3."));```

und renderer:

```public class FWListRenderer implements ListCellRenderer<Step> {

	public FWListRenderer() {

	}

	@Override
	public Component getListCellRendererComponent(JList<? extends Step> list,
			Step value, int index, boolean isSelected, boolean cellHasFocus) {
		// TODO Auto-generated method stub
		if (isSelected) {
			value.setBackground(Color.BLUE);
		} else {
			value.setBackground(Color.WHITE);
		}
		value.setStep(index + 1);
		System.out.println("werde aufgerufen");
		return value;
	}

}

Damit untergräbst du das Rendering Konzept der JList und könntest eigentlich wie vorgeschlagen ein JPanel mit Box Layout o.ä. verwenden.

Sicher dass der Renderer nicht aufgerufen wird? Die Objekte sind doch zu sehen?

Problematisch - neben dem Aushebeln des Renderings - ist das Du ein Null Layout verwendest und Dich nicht um die korrekte Größe Deiner Komponente kümmerst. Ausschlaggebend für den Renderer ist meines Wissens die PreferredSize.

[QUOTE=_Michael;29169]Damit untergräbst du das Rendering Konzept der JList und könntest eigentlich wie vorgeschlagen ein JPanel mit Box Layout o.ä. verwenden.
[/QUOTE]

ja damit habe ich es auch schon versucht dann habe ich aber das problem das ich mich um die selektion kümmern muss über ein mouseadapter oder so
möchte auch die position der elemente über drag&drop verändern können (innerhalb der liste) dachte dies ginge wenn ich eine jlist nehme einfacher

[QUOTE=_Michael;29169]
Sicher dass der Renderer nicht aufgerufen wird? Die Objekte sind doch zu sehen?[/QUOTE]
ja die system.out.println in meinem renderer wurde nie auf der console ausgegeben

problem lag vermutlich daran das ich kein model verwendet habe -.-

musste für die panels, wie du gesagt hast, noch die PreferredSize festlegen und ich füge die panels nun einem defaultlistmodel hinzu.
bisher habe ich es nun so gelöst:
erstmal panel von dem daten-objekt getrennt.
Meine Klasse zum anzeigen:


	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Step mystep = null;
	private final JLabel oidlbl, valuelbl, stepid;
	private final Font font = new Font("Tahoma", Font.PLAIN, 14);
	private final Font stepfont = new Font("Tahoma", Font.PLAIN, 30);

	public StepPanel(Step step) {
		this.mystep = step;
		setLayout(null);
		this.setBackground(Color.WHITE);
		this.setSize(310, 58);
		System.out.println(this.getSize());
		this.setPreferredSize(this.getSize());
		oidlbl = new JLabel("OID: " + mystep.getOid());
		oidlbl.setFont(font);
		oidlbl.setBounds(50, 10, 200, 14);
		add(oidlbl);
		valuelbl = new JLabel("value: " + mystep.getValue());
		valuelbl.setBounds(50, 34, 200, 14);
		valuelbl.setFont(font);
		add(valuelbl);
		stepid = new JLabel(String.valueOf(step));
		stepid.setBounds(5, 9, 40, 38);
		stepid.setFont(stepfont);
		add(stepid);
		this.setOpaque(true);
	}

}```

listen aufruf:

```		list = new JList<StepPanel>();
		DefaultListModel<StepPanel> listmod = new DefaultListModel<StepPanel>();
		list.setModel(listmod);
		list.setCellRenderer(new FWListRenderer());
		scrollPane2.setViewportView(list);
		list.setDragEnabled(true);
		list.setDropMode(DropMode.INSERT);

		listmod.addElement(new StepPanel(new Step("1.3.3.3.3.3.")));
		listmod.addElement(new StepPanel(new Step("1.3.3.3.3.3.", 2)));
		listmod.addElement(new StepPanel(new Step("1.3.3.3.3.3.", 3)));
		listmod.addElement(new StepPanel(new Step("1.3.3.3.3.3.", 4)));
		listmod.addElement(new StepPanel(new Step("1.3.3.3.3.3.", 5)));
		listmod.addElement(new StepPanel(new Step("1.3.3.3.3.3.", 6)));
		listmod.addElement(new StepPanel(new Step("1.3.3.3.3.3.", 7)));```

renderer habe ich nicht geändert der funktioniert jetzt wie geplant

Auch wenn es jetzt so funktioniert, würde ich aber trotzdem darüber nachdenken die Komponenten und die Darstellung dem Renderer zu überlassen.

dazu müsste dann mein renderer von jpanel erben?

Müssen nicht, er kann auch einfach nur ein JPanel mit den entsprechend platzierten Labels verwenden. Aber üblicherweise erben die Renderer von einer Komponente und stellen “sich selbst” zum rendern zur Verfügung.

danke dir - der renderer übernimmt jetzt komplett die darstellung,
jetzt muss ich nur noch dnd implementieren und die liste ist fertig

Uah, null layout. Ganz großes aua. http://www.leepoint.net/notes-java/GUI/layouts/nulllayout.html

welches Layout sollte ich dann verwenden?
im anhang ist das bild meiner JPanels, die ich anzeigen lasse. bis jetzt 3 labels pro jpanel.

ich tue mich mit den standard layouts schwer, finde die recht unbrauchbar bzw. umständlich.

für meine jframes habe ich in eclipse den windowbuilder,mit dem ich dann über das AbsoluteLayout meine komponenten in die größe und position ziehe. (ist auch nicht so toll, da bei fenster maximierung usw… die komponenten ihre größe behalten, aber wenn ich die komponenten, in dieser anordnung, mit einem standard-layout sortieren müsste würde das ja stunden dauern.)

mein neustes frame mit der liste sieht man im anhang

[japi]BorderLayout[/japi] ist für den Anfang immer eine gute Wahl. Oft muss man mehrere Panels mit verschiedenen Layouts schachteln, und das gewünschte Ergebnis zu erzielen. Wenn man Zeilen und Spalten auf einander abstimmen muss würde ich zum [JAPI]GroupLayout[/japi] greifen, aber da gibts auch schon einige externe Frameworks (zb.: JGoodies-FormLayout) die recht intuitiv anzuwenden sind.

GUI-Builder sind für mich immer bäh, weil die eben ein pixelgenaues Layout liefern, dass kaputt geht, wenn man die Fenstergröße ändert…

bye
TT

BorderLayout komibiniert mit GridLayout wäre eine Möglichkeit. Etwas unschön wäre dabei evtl. IDs mit unterschiedlicher Ziffernzahl. Da müsste man sich etwas überlegen. Eine bequeme Lösung:

import java.awt.Component;
import java.awt.Font;
import java.awt.GridLayout;

import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;

public class CustomListRendererDemo {
	public static void main(String[] args) {
		new CustomListRendererDemo().startDemo();
	}
	
	public void startDemo() {
		DefaultListModel<CustomObject> model = new DefaultListModel<CustomObject>();
		JList<CustomObject> list = new JList<CustomObject>(model);
		for (int i=0; i< 101; i++) {
			CustomObject obj = new CustomObject((char)(Math.random()*26 + 65)+" value", "value2");
			model.addElement(obj);
		}
		
		list.setCellRenderer(new CustomRenderer());
		
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setBounds(0, 0, 300, 300);
		frame.setLocationRelativeTo(null);
		frame.add(new JScrollPane(list));
		
		frame.setVisible(true);
	}
	
	class CustomRenderer extends JPanel implements ListCellRenderer<CustomObject> {
		private JLabel[] label;
		private final Font font = new Font("Tahoma", Font.PLAIN, 14);
		private JLabel labelMaxPreferredSize = new JLabel();
		
		public CustomRenderer() {
			label = new JLabel[] {new JLabel("", JLabel.RIGHT), new JLabel(), new JLabel()};
			setLayout(new BorderLayout(10, 10));
			JPanel panel = new JPanel(new GridLayout(2,1 ));
			panel.setOpaque(false);
			panel.add(label[1]);
			panel.add(label[2]);
			
			label[0].setFont(font.deriveFont(26f));
			labelMaxPreferredSize.setFont(font.deriveFont(26f));
			label[1].setFont(font);
			label[2].setFont(font);
			
			add(label[0], BorderLayout.WEST);
			add(panel, BorderLayout.CENTER);
		}
		
		public Component getListCellRendererComponent(JList<? extends CustomObject> list, CustomObject value, int index,
				boolean isSelected, boolean cellHasFocus) {
			if (isSelected)
				setBackground(list.getSelectionBackground());
			else
				setBackground(list.getBackground());
			labelMaxPreferredSize.setText(" " + (list.getModel().getSize()-1));
			
			label[0].setText(String.valueOf(index));
			label[0].setPreferredSize(labelMaxPreferredSize.getPreferredSize());
			
			label[1].setText("OID: " + value.value1);
			label[2].setText("value: " + value.value2);
			return this;
		}
	}
	
	class CustomObject {
		//public for dummy reasons
		public String value1, value2;
		
		public CustomObject(String value1, String value2) {
			this.value1 = value1;
			this.value2 = value2;
		}
	}
}```

[QUOTE=_Michael;29333]Etwas unschön wäre dabei evtl. IDs mit unterschiedlicher Ziffernzahl. [/QUOTE]für den Anfang könnte mann ja die PrefferedSize und die MinSize des entsprechenden Labels auf einen angemessenen Wert setzen…

bye
TT

ok danke, verwende halt die gui-builder weils einfach und schnell geht und ich nicht viel zeit in die gui investieren wollte.
jetzt habe ich allerdings die zeit das ich das noch anpassen könnte, wäre eigentlich schon notwendig. habe die software unter xp geschrieben und unter windows 7 schneidet es bei meinen fenstern unten immer etwas ab. also doch zeit in die gui investieren :twisted: