www.medienpunkt.com

  • Schrift vergrößern
  • Standard Schriftgröße
  • Schriftgröße verkleinern
Home

Nachrichtenfeld mit Formatierung

E-Mail Drucken

Oft ist es notwendig, für den Benutzer Statusmeldungen darzustellen. Dabei können die Meldungen in verschiedene Kategorien eingeteilt werden. So macht es Sinn, die Kategorien verschieden darzustellen, z.B. durch eine kleine Grafik oder die Textfarbe.

Im folgenden wird erklärt, wie man mit Hilfe einer JTextPane ein TextFeld mit verschiedenen Formatierungen für verschiedene Informationstypen erstellt. Das Beispiel nutzt unterschiediche Farben, um die Nachrichten darzustellen.

Um dem Nutzer der Klasse eine einfache Nutzung zu ermöglichen, wird eine Klasse ColoredMessagePane von der Klasse JPanel abgeleitet. Dadurch kann sie einfach mit Swing genutzt werden.

Als Ausgangspunkt für das Nachrichtenfenster dient die Klasse JTextPane. Sie ermöglicht durch die Nutzung eines DefaultStyledDocument die Formatierung von Text. Die Formatierungsvorgaben werden von einem StyleContext verwaltet. In der Klasse werden für jede der genannten Klassen private Referenzen deklariert.

Im Konstruktor wird eine Instanz eines StyleContext erzeugt und der Variable styleContext zugewiesen. Der styleContext wird dann dem Konstruktor der Klasse DefaultStyledDocument übergeben und die neue Instanz der Variable styleDoc zugewiesen. Mit Hilfe des Dokuments wird dann eine Instanz der Klasse JTextPane erzeugt und der Variable messageArea zugewiesen. Der Inhalt der JTextPane messageArea wird nun durch das DefaultStyledDocument styledDoc verwaltet, die Darstellung kann mit Hilfe des StyleContext styleContext zugewiesen werden.

import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Style;
import javax.swing.text.StyleContext;

public class ColoredMessagePane extends JPanel
{
private static final long serialVersionUID = 2041700181167824029L;
private StyleContext styleContext = null;
private DefaultStyledDocument styledDoc = null;
private JTextPane messageArea = null;

public ColoredMessagePane()
{
// Create the StyleContext, the document and the pane
styleContext = new StyleContext();
styledDoc = new DefaultStyledDocument(styleContext);
messageArea = new JTextPane(styledDoc);
}
}

Nun müssen wir noch definieren, welche Styles es gibt. Dies geschieht in der Funktion createStyles():

private void createStyles() {
// Create and add the main document style
Style defaultStyle = styleContext.getStyle(StyleContext.DEFAULT_STYLE);
Style mainStyle = styleContext.addStyle("MainStyle", defaultStyle);
StyleConstants.setForeground(mainStyle, Color.black);
Style informationStyle = styleContext.addStyle("InformationStyle", defaultStyle);
StyleConstants.setForeground(informationStyle, informationColor);
Style errorStyle = styleContext.addStyle("ErrorStyle", defaultStyle);
StyleConstants.setForeground(errorStyle, errorColor);
Style debugStyle = styleContext.addStyle("DebugStyle", defaultStyle);
StyleConstants.setForeground(debugStyle, debugColor);
// Set the logical style
styledDoc.setLogicalStyle(0, mainStyle);
}

Die Methode createStyleSheet() wird in dem Konstruktor der Klasse aufgerufen.

Das JTextPane muss nun noch dem JPanel zugefügt werden. Hier reicht die nutzung des BorderLayout aus. das JTextPane wird dabei als zentriert definiert:

private void arrangeWidgets() 
{
// just one element, use BorderLayout
this.setLayout(new BorderLayout());
this.add(messageArea, BorderLayout.CENTER);
}

Die Methode arrangeWidgets() wird ebenfalls im Konstruktor der Klasse aufgerufen.

Um die Informationstypen sauber zu definieren, benötigen wir noch eine Aufzählung, die die nutzbaren Informationsarten auflistet:

public enum InformationType
{
DEFAULT,
DEBUG,
INFORMATION,
ERROR
};

Schliesslich benötigen wir noch eine Methode, die es ermöglicht, Text an das DefaultStyledDocument zu übergeben. Dazu wird die Methode addMessage() genutzt. Sie hängt den angegebenen Puffer an das Dokument an und setzt die Attribute des eingefügten Textes entsprechend der Vorgaben. dazu muss der Methode die Informationsart und der anzuhängende String übergeben werden.

/** adds a message to the text field and scrolls down the field
* No break will be added at the end of the line.
* @param message Message to be appended
* @param type InformationType to specify the format of the message
*/
public void addMessage (InformationType type, String message)
{
try
{
int startLength = styledDoc.getLength();
styledDoc.insertString(startLength, message, null);
int numberOfInsertedChars = styledDoc.getLength() - startLength;
switch (type) {
case INFORMATION:
styledDoc.setCharacterAttributes(startLength,
numberOfInsertedChars, styleContext.getStyle("InformationStyle"), false);
break;
case DEBUG:
styledDoc.setCharacterAttributes(startLength,
numberOfInsertedChars, styleContext.getStyle("DebugStyle"), false);
break;
case ERROR:
styledDoc.setCharacterAttributes(startLength,
numberOfInsertedChars, styleContext.getStyle("ErrorStyle"), false);
break;
}
} catch (BadLocationException e) {
String msg = "Could not add message to message field.";
msg += "\nError is: ";
msg += e.getMessage();
JOptionPane.showMessageDialog(
null, msg, "Warning", JOptionPane.WARNING_MESSAGE);
}
messageArea.setCaretPosition(messageArea.getDocument().getLength());
messageArea.repaint();
}

/** adds a message to the text field and scrolls down the field
* A line break will be added at the end of the line.
* @param message Message to be appended
* @param type InformationType to specify the format of the message
*/
public void addMessageWithLineBreak (InformationType type, String message)
{
addMessage(type, message + "\n");
}

Nachdem die Information eingefügt wurde, wird der Cursor an das Ende gesetzt und die Komponente neu gezeichnet.

Zusätzlich gibt es die Method addMessageWithLineBreak(), welche einen Zeilenumbruch hinter dem Text einfügt.

Der gesamte Code der Klasse ColoredMessagePane sieht wie folgt aus:

import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;

public class ColoredMessagePane extends JPanel
{
public enum InformationType
{
DEFAULT,
DEBUG,
INFORMATION,
ERROR
};

private static final long serialVersionUID = 2041700181167824029L;
private StyleContext styleContext = null;
private DefaultStyledDocument styledDoc = null;
private JTextPane messageArea = null;
private final Color informationColor = Color.blue;
private final Color errorColor = Color.red;
private final Color debugColor = Color.green;

public ColoredMessagePane()
{
// Create the StyleContext, the document and the pane
styleContext = new StyleContext();
styledDoc = new DefaultStyledDocument(styleContext);
messageArea = new JTextPane(styledDoc);

createStyles();
arrangeWidgets();
}

private void createStyles()
{
// Create and add the main document style
Style defaultStyle = styleContext.getStyle(StyleContext.DEFAULT_STYLE);
Style mainStyle = styleContext.addStyle("MainStyle", defaultStyle);
StyleConstants.setForeground(mainStyle, Color.black);
Style informationStyle = styleContext.addStyle("InformationStyle", defaultStyle);
StyleConstants.setForeground(informationStyle, informationColor);
Style errorStyle = styleContext.addStyle("ErrorStyle", defaultStyle);
StyleConstants.setForeground(errorStyle, errorColor);
Style debugStyle = styleContext.addStyle("DebugStyle", defaultStyle);
StyleConstants.setForeground(debugStyle, debugColor);

// Set the logical style styledDoc.setLogicalStyle(0, mainStyle);
}

private void arrangeWidgets()
{
// just one element, use BorderLayout
this.setLayout(new BorderLayout());
this.add(messageArea, BorderLayout.CENTER);
}


/** adds a message to the text field and scrolls down the field
* No break will be added at the end of the line.
* @param message Message to be appended
* @param type InformationType to specify the format of the message
*/
public void addMessage (InformationType type, String message)
{
try
{
int startLength = styledDoc.getLength();
styledDoc.insertString(startLength, message, null);
int numberOfInsertedChars = styledDoc.getLength() - startLength;
switch (type)
{
case INFORMATION: styledDoc.setCharacterAttributes(startLength, numberOfInsertedChars,
styleContext.getStyle("InformationStyle"), false);
break;
case DEBUG: styledDoc.setCharacterAttributes(startLength, numberOfInsertedChars,
styleContext.getStyle("DebugStyle"), false);
break;
case ERROR: styledDoc.setCharacterAttributes(startLength, numberOfInsertedChars,
styleContext.getStyle("ErrorStyle"), false);
break;
}
} catch (BadLocationException e) {
String msg = "Could not add message to message field.";
msg += "\nError is: ";
msg += e.getMessage();
JOptionPane.showMessageDialog( null, msg, "Warning", JOptionPane.WARNING_MESSAGE );
}
messageArea.setCaretPosition(messageArea.getDocument().getLength());
messageArea.repaint();
}

/** adds a message to the text field and scrolls down the field
* A line break will be added at the end of the line.
* @param message Message to be appended
* @param type InformationType to specify the format of the message
*/

public void addMessageWithLineBreak (InformationType type, String message)
{
addMessage(type, message + "\n");
}

} // end of class

Die Klasse kann wie eine JPane einfache mit Hilfe eines Layout Managers zu einer Swing-Oberfläche hinzugefügt werden.
 

Anmeldung