# CSS in JEditorPane



## Webmaster Pazi (2. Nov 2010)

Hallöchen Leute!

Habe ein Problem mit folgenden CSS-Attributen in JEditorPane:

border-bottom-color, border-bottom-width und border-bottom-style

Das JEditorPane ignoriert diese Attribute und lässt den Style einfach weg?!

Hat jemand eine Idee was da los ist? Denn das JEditorPane ist auf text/html eingestellt und das kit
für den StyleSheet ist hinzugefügt...


----------



## XHelp (2. Nov 2010)

Es wird nicht 100% css unterstützt, deswegen würde ich einfach drauf tippen, dass diese Attributen nicht unterstützt werden. Vor allem wenn andere gehen.


----------



## Webmaster Pazi (2. Nov 2010)

Hmm schade eigentlich, dass html und css in java so eingerschänkt ist. gäb es denn eine möglichkeit das irgendwie selbst zu "rendern" oder gibt es dafür vllt. geeignete lib's ?


----------



## Wildcard (2. Nov 2010)

Wenn du nicht an Swing gebunden bist kannst du SWT verwenden. Das SWT Browser Widget embedded den OS Browser und bringt daher die kompletten Rendering und CSS capabilities eines modernen Browsers mit.


----------



## XHelp (3. Nov 2010)

Ich selber habe schon mal mit dem xhtmlrenderer etwas basteln müssen. Aber wie der Name schon sagt, geht es da eher um XHTML


----------



## Webmaster Pazi (3. Nov 2010)

Also Eclipse zeigt mir das package org.w3c.dom.
Wäre das nicht auch eine Lösung, also gäbs da einen renderer, der vllt. (wenigstens border von elementen) rendern kann?


----------



## XHelp (3. Nov 2010)

DOM hat so ziemlich nichts mit rendern zu tun...


----------



## Webmaster Pazi (3. Nov 2010)

Das stimmt schon. Jedoch laut API (CSSStyleSheet (Common DOM API)) kann die lib aber noch mehr.


----------



## XHelp (3. Nov 2010)

> The CSSStyleSheet interface is a concrete interface *used to represent a CSS style sheet* i.e., a style sheet whose content type is "text/css".


Es repräsentiert CSS, rendern ist eine ganz andere Sache.


----------



## Webmaster Pazi (3. Nov 2010)

Wildcard hat gesagt.:


> Wenn du nicht an Swing gebunden bist kannst du SWT verwenden. Das SWT Browser Widget embedded den OS Browser und bringt daher die kompletten Rendering und CSS capabilities eines modernen Browsers mit.



Dann bleibt mir wohl nichts anderes übrig als das


----------



## Webmaster Pazi (3. Nov 2010)

Also laut CSS (Java 2 Platform SE 5.0)
Funktionieren nur einige Attribute, darunter gibt es eine 2. Liste, die jedoch nicht von der Rendering Engine nicht verarbeitet wird.


```
The following are modeled, but currently not rendered.
    ...
    border-top-width (this is used to indicate if a border should be used)
    border-right-width
    border-bottom-width
    border-left-width
    border-width
    border-top
    border-right
    border-bottom
    border-left
    border
    ...
```

Und genau die Border-Attribute benötige ich, mehr schon nicht. Und das mit dem SWT Widget kann auch nicht Funktionieren, denn in dem JEditorPane ist reines HTML und keine SWT/Swing Komponenten


----------



## XHelp (3. Nov 2010)

Webmaster Pazi hat gesagt.:


> Und genau die Border-Attribute benötige ich, mehr schon nicht.


Es steht doch da, dass es nicht gerendert wird :bahnhof:


Webmaster Pazi hat gesagt.:


> Und das mit dem SWT Widget kann auch nicht Funktionieren, denn in dem JEditorPane ist reines HTML und keine SWT/Swing Komponenten



Hm??


----------



## Tomate_Salat (3. Nov 2010)

dient der JEditorPane rein der Anzeige oder wirklich als Editor?


----------



## Webmaster Pazi (3. Nov 2010)

Tomate_Salat hat gesagt.:


> dient der JEditorPane rein der Anzeige oder wirklich als Editor?



Nur als Anzeige, der Inhalt ändert sich jedoch ständig. Gäbs denn eine andere Lösung mit CSS?
Denn HTML wäre wirklich wichtig.


----------



## XHelp (3. Nov 2010)

Es wurden hier sogar 2 genannt, eben der xhtml renderer (falls du selber die html baust) und swt browser widget: Beispiel


----------



## Tomate_Salat (3. Nov 2010)

dann nimm SWT oder einen Swing-browser ausm internet (beispiel:DJ Project).


----------



## Webmaster Pazi (3. Nov 2010)

Ja, also ich werde dass dann nicht in HTML machen sondern mit Tk-UI - CSS Engine

Da gäbs jedoch nen Problem, wenn neue Texte hinzukommen, wo soll ich diese dann "draufpacken" ?

Übrigens: Es soll ein Chat-Fenster werden, deswegen dachte ich vorhin an HTML und CSS (für den Content der Texte, Usernamen,...), aber da ich
mit HTML ja keinen einfluss auf Java habe (z.b. mit HTML actionlisteners auslösen etc) werde ich das wohl auf Swing basiert coden müssen. Also bleibt mir die Frage, wie ich dann neue panels (mit Texten von Benutzern) hinzufüge. Denn kommen da einmal an die über 300 neue panel's wird das dann sicher 
an der Performance leiden.


----------



## XHelp (3. Nov 2010)

Webmaster Pazi hat gesagt.:


> Übrigens: Es soll ein Chat-Fenster werden, deswegen dachte ich vorhin an HTML und CSS (für den Content der Texte, Usernamen,...),


Dann brauchst du ja keine Engine, die dir zu der gesamten GUI css dranschraubt, oder? :bahnhof:


Webmaster Pazi hat gesagt.:


> aber da ich mit HTML ja keinen einfluss auf Java habe (z.b. mit HTML actionlisteners auslösen etc) werde ich das wohl auf Swing basiert coden müssen.



Den Vorschlag von Tomate_Salat habe ich zwar selber nie verwendet, bin mir aber sicher, dass du da sowas wie ein DocumentListener dranschrauben kannst und dadurch dein Programmfluss steuern kannst. (Links anklicken, etc pp)


Webmaster Pazi hat gesagt.:


> Also bleibt mir die Frage, wie ich dann neue panels (mit Texten von Benutzern) hinzufüge.


das macht kein Sinn


----------



## slawaweis (3. Nov 2010)

Webmaster Pazi hat gesagt.:


> Übrigens: Es soll ein Chat-Fenster werden, deswegen dachte ich vorhin an HTML und CSS (für den Content der Texte, Usernamen,...), aber da ich
> mit HTML ja keinen einfluss auf Java habe (z.b. mit HTML actionlisteners auslösen etc) werde ich das wohl auf Swing basiert coden müssen. Also bleibt mir die Frage, wie ich dann neue panels (mit Texten von Benutzern) hinzufüge. Denn kommen da einmal an die über 300 neue panel's wird das dann sicher
> an der Performance leiden.


Du brauchst eine JList, einen eigenen ListCellRenderer und ein eigenes Datenmodel für die Inhalte. Auf diese Weise kannst Du auch 10.000 Einträge im Chat darstellen.

Slawa


----------



## Webmaster Pazi (4. Nov 2010)

slawaweis hat gesagt.:


> Du brauchst eine JList, einen eigenen ListCellRenderer und ein eigenes Datenmodel für die Inhalte. Auf diese Weise kannst Du auch 10.000 Einträge im Chat darstellen.
> 
> Slawa



Vielen Dank 

Meine Frage dazu: Wie sollte ich das am besten realisieren (Sorry, aber bin noch nicht so der Java-Pro) ?
Ein kleines Tut oder ein Code-Beispiel wäre mir sicher hilfreich!


----------



## slawaweis (4. Nov 2010)

Webmaster Pazi hat gesagt.:


> Vielen Dank
> 
> Meine Frage dazu: Wie sollte ich das am besten realisieren (Sorry, aber bin noch nicht so der Java-Pro) ?
> Ein kleines Tut oder ein Code-Beispiel wäre mir sicher hilfreich!


Hier ist ein gutes Beispiel:

An example of the JList component in action : ListSwing JFCJava

BookEntry ist das Datenmodel und BookCellRenderer der ListCellRenderer.

Slawa


----------



## Webmaster Pazi (4. Nov 2010)

Klasse! Vielen Dank für die Hilfe! 

Ich werd mir das mal Ansehen


----------



## Webmaster Pazi (4. Nov 2010)

Lässt sich der Text auch in 2 oder 3 Zeilen Teilen ? Das wäre wichtig für einen Chat


----------



## slawaweis (5. Nov 2010)

Webmaster Pazi hat gesagt.:


> Lässt sich der Text auch in 2 oder 3 Zeilen Teilen ? Das wäre wichtig für einen Chat


der CellRenderer ist eine beliebige Komponente, die man nur vor dem jeweiligen Rendern richtig setzen muss. Du kannst Dir also ein Panel mit allem möglichen bauen, inklusive einer JEditorPane und HTML-Formatierung eines Chat-Eintrages. Ein DefaultStyledDocument und JTextArea wäre hier aber einfacher.

Slawa


----------



## Webmaster Pazi (5. Nov 2010)

Lassen sich denn keine Buttons hinzufügen zur JList? Ich möchte gernen Statt die Icons Buttons hinzufügen, jedoch nimmt mir der Renderer die buttons per add() nicht an?! (Diese Buttons werden dann als "Link" genutzt, wenn man zum Beispiel auf den Benutzernamen klickt, dass das Profil erscheint).

Was kann ich da machen ?


----------



## slawaweis (5. Nov 2010)

Webmaster Pazi hat gesagt.:


> Lassen sich denn keine Buttons hinzufügen zur JList? Ich möchte gernen Statt die Icons Buttons hinzufügen, jedoch nimmt mir der Renderer die buttons per add() nicht an?! (Diese Buttons werden dann als "Link" genutzt, wenn man zum Beispiel auf den Benutzernamen klickt, dass das Profil erscheint).


der Renderer ist deine JComponent, die kann alles aufnehmen. Allerdings ist der Renderer nicht interaktiv. Dazu musst Du den CellEditor implementieren. Wie mir gerade erst jetzt aufgefallen ist, unterstützt JList keine CellEditoren, d.h. Du musst eine einspaltige JTable verwenden, hier ist ein Beispiel:

Editable List Example : ListSwing ComponentsJava

Weiterhin möchte ich noch auf JXHyperlink aus SwingX verweisen, was ein wirklicher visueller Link in Swing ist. Ändert aber nichts daran, dass man einen CellEditor braucht.

SwingX: Consider JXHyperlink As An Alternative To Buttons

Slawa


----------



## Webmaster Pazi (6. Nov 2010)

Wie kann man die Spaltenbeschreibung (oben der name der Spalte) ausblenden?







Ein Beispielcode von: JTable Examples


----------



## slawaweis (6. Nov 2010)

entweder


```
table.setTableHeader(null);
```

oder


```
table.getTableHeader().setVisible(false);
```

Slawa


----------



## Webmaster Pazi (7. Nov 2010)

Ah genau !

So ich hab die JTable endlich fast fertig! Ein Problem gibts noch mit dem Rendern mehrerer Zeilen.
Ich kann auch nicht auf den Text zugreifen (2. Spalte) der wird komischerweise auch ohne renderer angezeigt?! Hier mal der Code:

JButtonTableExample.java

```
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;

public class JButtonTableExample extends JFrame {

  public JButtonTableExample(){
    super( "JButtonTable Example" );
    
    DefaultTableModel dm = new DefaultTableModel() {
        public boolean isCellEditable(int row, int column) {
            if (column == 1) {
                return false;
            } else {
                return true;
            }
          }
    };
    dm.setDataVector(new Object[][]{{"Username","Texttext"},
                                    {"Username","Texttext 2 Text Text Text Text Text Text Text Text Text Text Text"}},
                     new Object[]{"username","message"});
                     
    JTable table = new JTable(dm);
    table.setShowGrid(false);
    table.setCellSelectionEnabled(false);
    table.setFocusable(false);
    table.setTableHeader(null);
    table.getColumn("username").setCellRenderer(new ButtonRenderer());
    table.getColumn("username").setCellEditor(new ButtonEditor(new JCheckBox()));
    table.getColumn("username").setMinWidth(200);
    table.getColumn("username").setMaxWidth(200);
    table.getColumn("message").setCellRenderer(new LabelRenderer());
    table.getColumn("message").setCellEditor(new LabelEditor(new JCheckBox()));
    JScrollPane scroll = new JScrollPane(table);
    getContentPane().add( scroll );
    setSize( 400, 100 );
    setVisible(true);
  }

  public static void main(String[] args) {
    JButtonTableExample frame = new JButtonTableExample();
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
}
```

ButtonEditor.java

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

import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;

public class ButtonEditor extends DefaultCellEditor {
  protected JButton button;
  private String    label;
  private boolean   isPushed;

  public ButtonEditor(JCheckBox checkBox) {
    super(checkBox);
    button = new JButton();
    button.setOpaque(true);
    button.setHorizontalAlignment(SwingConstants.LEFT);
    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        fireEditingStopped();
      }
    });
  }

  public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
    if (isSelected) {
      button.setForeground(table.getSelectionForeground());
      button.setBackground(table.getSelectionBackground());
    } else {
      button.setForeground(table.getForeground());
      button.setBackground(table.getBackground());
    }
    label = (value ==null) ? "" : value.toString();
    button.setText( label );
    isPushed = true;
    return button;
  }

  public Object getCellEditorValue() {
    if (isPushed)  {
      // 
      // 
      JOptionPane.showMessageDialog(button ,label + ": Ouch!");
      // System.out.println(label + ": Ouch!");
    }
    isPushed = false;
    return new String( label ) ;
  }
  
  public boolean stopCellEditing() {
    isPushed = false;
    return super.stopCellEditing();
  }

  protected void fireEditingStopped() {
    super.fireEditingStopped();
  }
}
```

ButtonRenderer.java

```
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

public class ButtonRenderer extends JButton implements TableCellRenderer {

  public ButtonRenderer() {
    setOpaque(true);
    this.setHorizontalAlignment(SwingConstants.LEFT);
  }
  
  public Component getTableCellRendererComponent(JTable table, Object value,
                   boolean isSelected, boolean hasFocus, int row, int column) {
    if (isSelected) {
      setForeground(table.getSelectionForeground());
      setBackground(table.getSelectionBackground());
    } else{
      setForeground(table.getForeground());
      setBackground(UIManager.getColor("Button.background"));
    }
    setText( (value ==null) ? "" : value.toString() );
    return this;
  }
}
```

LabelEditor.java

```
import java.awt.Component;

import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JTable;

public class LabelEditor extends DefaultCellEditor {
    
    private JLabel label;
    
    public LabelEditor(JCheckBox checkBox) {
        super(checkBox);
        label = new JLabel();
    }
    
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        label.setText("");
        return label;
      }

}
```

LabelRenderer.java

```
import java.awt.Component;

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

public class LabelRenderer extends JTextArea implements TableCellRenderer {
    
    public void LabelRenderer() {
        this.setEditable(false);
        this.setLineWrap(true);
        this.setWrapStyleWord(true);
    }
 
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
        this.setText(value.toString());
        return this;
    }
}
```


----------



## slawaweis (8. Nov 2010)

Webmaster Pazi hat gesagt.:


> So ich hab die JTable endlich fast fertig! Ein Problem gibts noch mit dem Rendern mehrerer Zeilen.
> Ich kann auch nicht auf den Text zugreifen (2. Spalte) der wird komischerweise auch ohne renderer angezeigt?! Hier mal der Code:


ich habe mir den Code ansehen. In der Klasse JButtonTableExample, in isCellEditable markierst Du die zweite Spalte als nicht editierbar, deshalb kannst Du nicht auf den Text zugreifen:


```
@Override
        public boolean isCellEditable(int row, int column) {
            if (column == 1) {
                return false; // zweite Spalte nicht editierbar
            } else {
                return true;
            }
          }
```

Weiterhin hast Du den Konstruktor in LabelRenderer als Funktion deklariert, was das andere Problem erklären sollte.

Slawa


----------



## Webmaster Pazi (8. Nov 2010)

Stimmt, deswegen wurde der Text nicht übernommen und der Kontruktor wurde zu einer Funktion, die nicht augerufen werden konnte 

Beim LabelRenderer der die Funktionen von JTextArea implementiert, sollte eigentlich bei zu viel Text den Text so ändern, dass er in die 2. Zeile der Zelle geschrieben wird, was er aber nicht tut, habe das mal mit JLabel versucht, jedoch scheiterte das, denn der Text wurde "unter" die Zelle geschoben. Lässt sich da nichts andere machen? Zb. die Zellenhöhe erweitern?

So, nochmals vielen Dank!


----------



## slawaweis (8. Nov 2010)

Webmaster Pazi hat gesagt.:


> Beim LabelRenderer der die Funktionen von JTextArea implementiert, sollte eigentlich bei zu viel Text den Text so ändern, dass er in die 2. Zeile der Zelle geschrieben wird, was er aber nicht tut, habe das mal mit JLabel versucht, jedoch scheiterte das, denn der Text wurde "unter" die Zelle geschoben. Lässt sich da nichts andere machen? Zb. die Zellenhöhe erweitern?


Du musst entweder setPrefferedSize in dem CellRenderer und CellEditor setzen oder setRowHeight in JTable.

Slawa


----------



## Webmaster Pazi (8. Nov 2010)

slawaweis hat gesagt.:


> Du musst entweder setPrefferedSize in dem CellRenderer und CellEditor setzen oder setRowHeight in JTable.
> 
> Slawa



Du meinst setPrefferedSize bei LabelRenderer, oder?
Das kann aber nicht funktionieren wenn ich eine feste größe mache, oder?


----------

