Model oder Renderer für JList

Jelena01

Grünschnabel
Liebe Gemeinde,

Folgendes Problem:
In einer Liste eines Java-Applets werden Daten über JTextFields aufgenommen. Die Liste soll das gleiche Aussehen haben, wie die Liste, die nach einem Datenbankabruf der aufgenommenen Daten in einer HTML-Seite dargestellt werden.

Dazu verwende ich ein Listenmodel mit HTML-Tags. Das funktioniert auch.
Bsp.:
Code:
---------------------------------
| Datum | Inhalt 1    | Grafik  |
|       |-------------|         |
|       | Inhalt 2    |         |
---------------------------------
</pre>
Die Grafik lade ich vom Server via CGI. Das HTML-Tag sieht also so aus:

Code:
<img src=www.server.de/holegrafik.cgi?key=value>

Java-Quellcode:
Code:
model += "<td><img src=" + getTheImage() + ">";


getTheImage() liefert oben genannte Adresse.
Soweit, so gut.

Das Problem:
Immer, wenn ich einen Datensatz hinzufüge, holt sich das Applet die Grafik neu vom Server, weil ja im HTML-Tag diese Adresse steht.
Schalte ich ein BufferedImage dazwischen, das die Grafik im Speicher hält, dann kann der HTML-Interpreter nichts damit anfangen und anstelle der Grafik wird, auch logisch, nur die Adresse des ImageIcon angezeigt, nicht die Grafik selbst.
Jetzt habe ich mir gedacht, dass, wenn denn die Grafik schon direkt geholt werden muß, ich einfach noch ein Meta-Tag unterbringe, in dem ich festlege, dass die Grafik gecacht werden soll. Ist ja auch HTML und müßte genau so berücksichtigt werden, wie alle anderen Tags auch. Aber das funktioniert auch nicht. Ich benötige aber für die Listeneinträge unbedingt eine derartige Darstellung.
Kann man das mit einem Renderer realisieren und wenn ja, wie fange ich das an? Oder gibt es gar für das Model eine Lösung?

Danke im Voraus
 
Hallo,

also für das Model gibt es keine Lösung. Aber nicht deswegen, weil es nicht möglich ist, sondern weil das Model dafür nicht gedacht ist.

Du musst das ganze nicht mit HTML machen. Der Klasse ImageIcon kann man im Kontruktor eine URL übergeben. Damit kannst du für das Bild ein ImageIcon verwenden.
Für die komplette Darstellung könntest du dir im Renderer ein JPanel zusammenbauen und das dann zurückgeben.

MFG

Sascha
 
Danke Sascha.

Das Problem hatte ich soweit schon erkannt. Ich verwende tatsächlich ein ImageIcon, dem ich die Url übergebe. Nur das diese Url bei jedem Listeneintrag neu aufgerufen wird und dadurch ein Performance-Verlußt auftritt. Da die Liste in einem Applet steht, macht das Applet bei jedem Hinzufügen oder Auswählen einen Connect zum Server, was bei langsamen Verbindungen schon mal nerven kann.

Ok. bis dahin. Wie könnte so ein Renderer aussehen. Damit habe ich mich noch nie beschäftigt.
ein kleines Beispiel für zwei Spalten pro Listeneintrag würde mir schon helfen, so dass ich halt einen Eindruck gewinne, mit dem ich diesen hemmenden Respekt vor dem Begriff Renderer loswerden kann.

Danke
 
Ich verwende tatsächlich ein ImageIcon, dem ich die Url übergebe. Nur das diese Url bei jedem Listeneintrag neu aufgerufen wird und dadurch ein Performance-Verlußt auftritt.

Das passiert nicht, wennd du das Icon nicht immer neu anlegst, sondern in dem Renderer als Klassenvariable deklarierst. So wird das Icon nur einmal angelegt und das Applet braucht sich nur einmal mit dem Server zu verbinden.

Das mit einen Renderer ist nicht allzu schwer. Du schreibst du einfach eine Klasse die dieses Interface implementiert. In der zu implementierenden Methode gibst du dann einfach eine Component zurück. Das kann ein JLabel, JPanel, JButton usw sein. Auf diese Compontent kannst du drauf packen was du möchtest.

In deinem Fall brauchst du einfach ein JPanel. Da packst du dann 2 JLabel drauf und das gibst du dann im Renderer zurück.
Achte aber drauf, dass du nicht immer ein neues Object in der Renderer-Methode anlegst, da sonst für jede Zeile eine neues Object angelegt wird und das muss nicht sein.

Versuch es mal so, wenn du es nicht schaffst, zeige ich dir mal ein Beispiel. Im Moment habe ich leider nicht genug Zeit.

MFG

Sascha
 
Hallo Sascha,

Bin jetzt erst wieder von einer Reise zurückgekehrt und sitze wieder an diesem Problem. Danke für Deine Anwort.
Ich habe jetzt einen Renderer geschrieben und der funktioniert auch soweit, wenn ich ein GridBagLayout verwende. Da aber eine genaue Positionierung nicht mehr möglich ist, wenn die Textinhalte unterschiedlich lang sind, habe ich es mit einem NullLayout versucht. Während ich in den meisten Fällen ohne Layoutmanager arbeite, hatte ich gedacht, dass das auch bei einem ListCellRenderer funktionieren sollte.
Entweder mache ich etwas falsch und sehe gerade den Wald vor lauter Bäumen nicht. Fact ist, dass Daten in die Liste aufgenommen werden. Wenn ich also in das Panel klicke bekomme ich die Daten auch in den Textfeldern zum bearbeiten angezeigt. Die Liste selbst zeigt die Einträge aber nicht an.

hier mal der Renderer:
HTML:
<pre>
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
  // Vier Zeilen, jeweils eine für Name und WebAdresse und Bild,   
  eine für eMail-Adresse, die linksbündig unter WebAdresse stehen soll.
  Person p = (Person) value;
  JPanel mypane = new JPanel();
 
  JLabel left = new JLabel();
  left.setText(p.getName());
  JLabel top = new JLabel();
  top.setText(p.getWww());
  JLabel bot = new JLabel();
  bot.setText(p.getEMail());
  JLabel rechts = new JLabel();
  rechts.setIcon(p.getImgIcon());
 
  left.setBounds(0,0,40,22);
  top.setBounds(0, 0, 100, 22);
  bot.setBounds(0, 22, 100, 22);
  rechts.setBounds(100, 0, 40, 40);
  mypane.setLayout(null);
  mypane.add(left);
  mypane.add(top);
  mypane.add(bot);
  mypane.add(rechts);
  return mypane;
  }
}
</pre>
 
Hallo Sascha,
das Problem existiert immernoch. Nachfolgend mal der komplette Code.
Ich weiss einfach nicht, was daran falsch sein soll.
Oder es hat wirklich was mit Wald und Bäumen zu tun?
HTML:
<pre>
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.Vector;
import javax.swing.AbstractListModel;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;

interface IAdrListModel extends ListModel {
void addElement(Object element);
void removeElement(int Index);
}

class MyList extends AbstractListModel implements IAdrListModel {
private final Vector data = new Vector();

public int getSize() {
return data.size();
}

public Object getElementAt(int index) {
return data.elementAt(index);
}

public void addElement(Object element) {
data.addElement(element);
fireIntervalAdded(this, data.size() - 1, data.size() - 1);
}

public void removeElement(int index) {
data.removeElementAt(index);
fireIntervalRemoved(this, index, index);
}
}

class Personal {
private final String name;
private final String www;
private final String eMail;
private final ImageIcon ii;

public Personal(String n, String w, String e) {
name = new String(n);
www = new String(w);
eMail = new String(e);
ii = getImgIcon();
}

public ImageIcon setImageIcon() {
ImageIcon ii = null;
ii = new ImageIcon("../img/logo.gif");
return ii;
}

public String getName() {
return name;
}

public String getWww() {
return www;
}

public String getEMail() {
return eMail;
}

public ImageIcon getImgIcon() {
return ii;
}
}

class AdrCellRenderer extends JPanel implements ListCellRenderer {

JLabel lft = null;
JLabel top = null;
JLabel bot = null;
JLabel rgt = null;

public JLabel getLft(String name) {
if (lft == null) {
lft = new JLabel();
lft.setText(name);
lft.setBounds(0, 0, 40, 22);

lft.setForeground(new Color(0, 0, 0));
}
return lft;
}

public JLabel getTop(String www) {
if (top == null) {
top = new JLabel();
top.setText(www);
top.setBounds(40, 0, 100, 22);
}
return top;
}

public JLabel getBot(String email) {
if (bot == null) {
bot = new JLabel();
bot.setText(email);
bot.setBounds(40, 22, 100, 22);
}
return bot;
}

public JLabel getRgt(ImageIcon ii) {
if (rgt == null) {
rgt = new JLabel();
rgt.setIcon(ii);
rgt.setBounds(140, 0, 40, 40);
}
return rgt;
}

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

Personal p = (Personal)value;
JPanel jPane = new JPanel();
jPane.setLayout(null);
jPane.add(getLft(p.getName()));
jPane.add(getTop(p.getWww()));
jPane.add(getBot(p.getEMail()));
jPane.add(getRgt(p.getImgIcon()));

return jPane;
}
}

public class AdrListCellRendererTest extends JFrame implements ActionListener {
MyList plist;
JTextField name, www, email;
JList people;

public AdrListCellRendererTest() {
super("ListLayout");

plist = new MyList();
people = new JList(plist);
people.setCellRenderer(new AdrCellRenderer());
JScrollPane scrollPane1 = new JScrollPane(people);
JButton add_person = new JButton("Add to list");
add_person.addActionListener(this);
add_person.setAlignmentX(Component.LEFT_ALIGNMENT);
name = new JTextField(40);
www = new JTextField(40);
email = new JTextField(40);

JPanel lists = new JPanel(false);
JPanel textfields = new JPanel(false);
JPanel main_panel = new JPanel(false);
lists.setLayout(new BoxLayout(lists, BoxLayout.X_AXIS));
textfields.setLayout(new BoxLayout(textfields, BoxLayout.Y_AXIS));
main_panel.setLayout(new BoxLayout(main_panel, BoxLayout.Y_AXIS));

textfields.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Data"));
main_panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
scrollPane1.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "Click to view"), scrollPane1.getBorder()));

lists.add(scrollPane1);
textfields.add(name);
textfields.add(www);
textfields.add(email);
textfields.add(add_person);
main_panel.add(lists);
main_panel.add(textfields);
setContentPane(main_panel);

MouseListener mousy = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
JList list = (JList) e.getSource();
int index = list.locationToIndex(e.getPoint());
if (index >= 0) {
name.setText(((Personal) plist.getElementAt(index)).getName());
www.setText(((Personal) plist.getElementAt(index)).getWww());
email.setText(((Personal) plist.getElementAt(index)).getEMail());

}
}
};

MouseListener remover = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
JList list = (JList) e.getSource();
int index = list.locationToIndex(e.getPoint());
if (index >= 0) {
plist.removeElement(index);
name.setText("");
www.setText("");
email.setText("");
}
}
};
people.addMouseListener(mousy);
}

public void actionPerformed(ActionEvent e) {
Personal p = new Personal(name.getText(), www.getText(), email.getText());
plist.addElement(p);
name.setText("");
www.setText("");
email.setText("");
name.requestFocus();
}

public static void main(String[] args) {
JFrame frame = new AdrListCellRendererTest();

WindowListener l = new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
};
frame.addWindowListener(l);
frame.pack();
frame.setVisible(true);
}
}
</pre
 
Hallo Sascha,
Problem gelöst. Des Pudels Kern:
setSize() getestet, ohne Erfolg, setBounds() getestet ohne Erfolg, Hilfe gerufen, ohne Erfolg.
Aber dann: setPrefferedSize probiert und alles im Lot.
Aber eine Frage hätte ich dann doch noch. Du schreibst, dass ich nicht jedes Mal ein neues JLabel anlegen solle. Aus Performancegründen. Das habe ich an anderen Stellen auch schon gelesen. Aber ohne geht das irgendwie auch nicht.
HTML:
<pre>
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {

Personal p = (Personal)value;
JPanel jPane = new JPanel();
jPane.setLayout(null);
// Die Sache mit den Bäumen und dem Wald.
jPane.setPreferredSize(new Dimension(280,50));
jPane.add(getLft(p.getName()));
jPane.add(getTop(p.getWww()));
jPane.add(getBot(p.getEMail()));
jPane.add(getRgt(p.getImgIcon()));

return jPane;
}
</pre>

Ganz grosses Dankeschön bis hierhin
jelena01
 

Neue Beiträge

Zurück