ich möchte einem DefaultListModel() eigene Objekte hinzufügen, und diese bei Auswahl weiter verarbeiten können.
Ich lasse die Liste als JList in meinem Fenster anzeigen.
Meine Frage ist: wie kann ich nur eine bestimmte Eigenschaft (also ein Memberfeld) der Objekte in der Liste anzeigen? UND dabei das Objekt selbst an Ort und stelle behalten?
Ich weiß nur, wie ich zb ein String-Feld des Objekts in der Liste darstellen kann. Folglich ist in der Liste aber dann auch nur ein String drin, und nicht mehr das Objekt.
Habe hier versucht exemplarisch (und unvollständig) alles mir wichtig erscheinende als Code darzustellen:
Java:
publicclassAuto{privateint kilometer;privateString farbe;//konstruktor, getter, setter}publicclassMyAutoModel{privateArrayList<Auto> autoListe =newArrayList<>();publicmyAutoModel(){Auto astra =newAuto(30000,"rot");
autoListe.add(astra);}//getter: getArrayList()...}publicclassMyAutoView{privateMyAutoModel model;privateDefaultListModel myList;publicMyAutoView(MyAutoModel model){this.model = model;initComponents();}privatevoidinitComponents(){
myList =newDefaultListModel();//GUI...
button.setText("open this object");
button.addActionListener(newActionListener(){publicvoidbuttonClickActionPerformed(ActionEvent evt){openActionPerformed(evt);}}privatevoidbuttonClickActionPerformed(ActionEvent evt){for(int i =0; i < model.getArrayList().size(); i++){
myList.addElement(model.getArrayList().get(i).getFarbe());}}//hier würde ich nun die Farbe ausgegeben bekommenSystem.out.println(myList.getElementAt(0));}
Eigentlich möchte ich mit getElementAt aber das Objekt selbst bzw die Objektreferenz erhalten, um mit diesem Objekt weiter zu arbeiten: ein neues Fenster erzeugen, und erst dort alle Membervariablen auslesen und darstellen.
Vl denk ich auch zu kompliziert und es ist eigentlich ganz einfach? :rtfm:
[c] myList.addElement(model.getFarbe());[/c]
mal davon abgesehen dass das model.getFarbe() generell falsch aussieht, musst du hier die Auto-Objekte hinzufügen. Bzw eig. hast du ja schon ein Model mit einer Liste, irgendwie ist das doppelt gemoppelt was du machst.
Aber zu deiner eigentlichen Frage:
Meine Frage ist: wie kann ich nur eine bestimmte Eigenschaft (also ein Memberfeld) der Objekte in der Liste anzeigen?
Indem du einfach die toString-Methode deiner Auto-Klasse überschreibst. Das würde dann zwar gehen, aber wohl nicht optimal. Ein eigener Renderer wäre dann noch eine Alternative!
Ja, müsste ich, damit ich mit ihnen arbeiten kann. Aber angezeigt bekomme ich dann ja so Speicheradressen wie Auto@2341223 angezeigt. Und ich würde in diesem Beispiel ja die Farbe wollen.
Die toString Methode ist leider schon an anderer Stelle überschrieben, für einen FileWriter.
"Renderer" sagt mir jetzt grad gar nichts. Vielleicht verfolge ich mit der JList aber auch den falschen Ansatz und das geht anders viel besser?? Ich wüsste nur nicht wie...
Diese beiden Aussagen passen meiner Meinung nach nicht zueinander. Auto@2341223 sieht nach der Default-Implementierung, also die Implementierung der Oberklasse Object aus, d.h. du hast die toString in deiner Auto-Klasse NICHT überschrieben!
(toString hatte ich tatsächlich nicht mehr überschrieben).
Noch eine Frage: mit getListCellRendererComponent(...) scheinen mir ja sämtliche Formatierungen der JList verloren zu gehen. zB kann ich auch nicht mehr markieren, die Schriftart sieht anders aus, irgendwie kleiner und näher zusammen gerückt.
Kann ich nicht irgendwie den Style der JList beibehalten?
//ich adde nun die Auto-Elemente mit:
myList.addElement(model.getArrayList().get(i));//die renderer klasse:classMyRendererextendsJLabelimplementsListCellRenderer{publicComponentgetListCellRendererComponent(JList list,Object value,int index,boolean isSelected,boolean cellHasFocus){//muss ich das hier casten?Auto tmp =(Auto) value;setText(tmp.getFarbe());returnthis;}}
Ich hätte eigentlich erwartet, dass ich mit value.getFarbe() irgendwie weitermachen kann. Aber das scheint nicht zu gehen, also muss ich vorher das Auto Objekt casten. Ist das richtig?
Irgendwie ist das konfus in meinem Kopf: ich sammel meine Auto-Objekte in einer ArrayList, damit ich alle zusammen bequem an den View reichen und adden kann. Und dann muss ich das zu addende Objekt doch wieder im Viewer zurückcasten, um an die Membervariablen zu kommen. Irgendwie dreht man sich da doch im Kreis?...
[c]Object value[/c]
Der Typ ist also Object. Der Compiler weiss an dieser Stelle nicht dass du da Auto-Objekte rein packen willst/getan hast, also musst du erst einmal casten um dann die Methoden deiner Auto-Klasse benutzen zu können. Das hat jetzt aber nichts mit Kreis drehen zu tun oder sonst was, sondern eher mit dem Interface: ListCellRenderer (Java Platform SE 6)
Meine Frage ist: wie kann ich nur eine bestimmte Eigenschaft (also ein Memberfeld) der Objekte in der Liste anzeigen? UND dabei das Objekt selbst an Ort und stelle behalten?
Ich würde das Modell default lassen und toString() Methode deines Objekts entprechend überschreiben. JList enthält dann die Objekte zeigt aber das was du in toString() definiert hast.
Ich würde das Modell default lassen und toString() Methode deines Objekts entprechend überschreiben. JList enthält dann die Objekte zeigt aber das was du in toString() definiert hast.
Dem kann ich nur zustimmen. Zumal Du auf die Weise schon die ganzen Autos hast, wenn Du damit weiterarbeiten möchtest (bspw. die Details anzeigen, wenn eins selektiert ist).
Ich habe es jetzt auch nochmal mit der toString() überschreiben Methode versucht, geht auch wunderbar.
Aber da ich den Listenstyle auch noch ändern will (zB ein Icon vor die Objekte setzen), werd ich das wohl mit dem Renderer machen müssen.
Oder gibt es noch abseits des Renderers eine Möglichkeit die JList appearance zu steuern?
Nein gibt es nicht, der Renderer definiert das Aussehen der Listeneinträge - mal abgesehen von begrenzt möglichen Manipulationen per überschriebener toString().
Ja genau. OK dann lass ich es so mit dem Renderer.
Mir ist gerade aber noch etwas aufgefallen, was ich nicht einordnen kann:
Die JList, die ich mit dem Renderer darstelle, sieht anders aus als wenn ich ihn nicht benutze. Auch wenn ich bloß folgendes schreibe:
Wie kann das sein?
Ich habe auch mal mit und ohne Renderer die getFont() ausgegeben. Ist exakt gleich. ABER wird anders dargestellt! Wie kommt das denn?
JList verwendet defaultmäßig DefaultListCellRenderer. Die Renderer Komponente ist hier zwar auch ein JLabel, dieses besitzt aber eine Border von 1 Pixel.
Kann ich irgendwie alle Style-Eigenschaften von DefaultListCellRenderer da implementieren?
Die renderer Liste sieht schon echt anders aus. Schrift ist kleiner und Buchstaben stehen enger, zwischen den Elementen ist weniger Space, der Hintergrund der Einträge wird nicht mehr farbig markiert beim selecten, usw.
/notfalls style ich halt selbst mit new EmptyBorder() und setBackground()...
Ja, kanst Du. Aber Du müsstest Deine Architektur leicht verändern, indem Du Deinen Renderer nicht von JLabel erben lässt, sondern von DefaultListCellRenderer. Dieser kann dann der JList zugewiesen werden über setCellRenderer().