Categories: MSDN / DotNet / Java / Scripts / Linux / PHP Ask - La ask - La Answer

Initializing font in JTextPane

I have a JTextPane that serves as part of my application. I want to initialize the font, size, color and style (bold, italic) of the font that will be used in the pane to start with before the user makes any changes. It seems to work for everything except the font family. Here's the code. If you run it, type in some text, change part of it to a different font and then move the caret around, the font selection, color, size and style controls should change to reflect the font characteristics at the current caret position. Like I said, it works for everything except the font family. I've tried many different ways of initializing the font but none seem to work.

Any ideas?
Thanks!

*** I'll have to put the code in a seperate post since it seems to be too long.
[807 byte] By [doubleoseven] at [2007-11-11 8:30:01]
# 1 Re: Initializing font in JTextPane
This is the first half

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusListener;
import java.awt.event.KeyListener;
import java.awt.font.TextAttribute;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ButtonModel;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultButtonModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextPane;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Element;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;
import javax.swing.text.StyleContext.NamedStyle;

/** Model */
class TE_Model {
private ButtonModel boldButtonModel = new DefaultButtonModel();
private ButtonModel italicButtonModel = new DefaultButtonModel();
private DefaultComboBoxModel fontSelectModel = new DefaultComboBoxModel();
private SpinnerModel fontSizeModel = new SpinnerNumberModel();
private StyledDocument myStyledDoc = new DefaultStyledDocument();

// Text Pane
public StyledDocument getStyledDocument() {
return myStyledDoc;
}

public Element getCharacterStyles(int i) {
return myStyledDoc.getCharacterElement(i);
}

public void setText(AttributedString string) {
if (string != null) {
AttributedCharacterIterator iter = string.getIterator();

// Get the unformatted text
String strippedText = new String();
while(iter.getIndex() < iter.getEndIndex()) {
strippedText = strippedText + iter.current();
iter.next();
}

// Clear the box
try {
myStyledDoc.remove(0, myStyledDoc.getLength());
}
catch (BadLocationException e) {
System.out.println("Bad location when removing text");
}

// Fill the box with the unformatted string
try {
myStyledDoc.insertString(0, strippedText, null);
}
catch (BadLocationException e) {
System.out.println("Bad location when inserting text");
}

iter.setIndex(0);

// Add the attributes to each character
while (iter.getIndex() < iter.getEndIndex()) {
//Font oldFont = (Font)iter.getAttribute(TextAttribute.FONT);
String oldFontFamily = iter.getAttribute(TextAttribute.FAMILY).toString();
int oldFontSize = Integer.parseInt(iter.getAttribute(TextAttribute.SIZE).toString());
Color oldFontColor = (Color)iter.getAttribute(TextAttribute.FOREGROUND);

SimpleAttributeSet attr = new SimpleAttributeSet();
//StyleConstants.setFontFamily(attr, oldFont.getFontName());
//StyleConstants.setFontSize(attr, oldFont.getSize());
StyleConstants.setFontFamily(attr, oldFontFamily);
StyleConstants.setFontSize(attr, oldFontSize);
StyleConstants.setForeground(attr, oldFontColor);
myStyledDoc.setCharacterAttributes(iter.getIndex(), 1, attr, true);
iter.next();
}
}
else {
// Clear the box
try {
myStyledDoc.remove(0, myStyledDoc.getLength());
}
catch (BadLocationException e) {
System.out.println("Bad location when removing text");
}
}
}

// Bold Button
public ButtonModel getBoldButtonModel() {
return boldButtonModel;
}

public boolean getBoldButtonState() {
return boldButtonModel.isSelected();
}

public void setBoldButtonState(boolean x) {
boldButtonModel.setSelected(x);
}

public void toggleBoldButton() {
boolean x = (boldButtonModel.isSelected()) ? false:true;
boldButtonModel.setSelected(x);
}

// Italic Button
public ButtonModel getItalicButtonModel() {
return italicButtonModel;
}

public boolean getItalicButtonState() {
return italicButtonModel.isSelected();
}

public void setItalicButtonState(boolean x) {
italicButtonModel.setSelected(x);
}

public void toggleItalicButton() {
boolean x = (italicButtonModel.isSelected()) ? false:true;
italicButtonModel.setSelected(x);
}

// Font Select
public ComboBoxModel getFontSelectModel() {
return fontSelectModel;
}

public void addFonts(Vector fonts) {
for (int i=0; i<fonts.size(); i++) {
fontSelectModel.addElement(fonts.elementAt(i));
}
}

public String getSelectedFontName() {
return fontSelectModel.getSelectedItem().toString();
}

public int getSelectedFontIndex() {
for (int i=0; i<fontSelectModel.getSize(); i++) {
if (fontSelectModel.getElementAt(i).equals(fontSelectModel.getSelectedItem())) {
return i;
}
}
return 0;
}

public void setFontSelection(int x) {
fontSelectModel.setSelectedItem(fontSelectModel.getElementAt(x));
}

public void setFontSelection(String x) {
for (int i=0; i<fontSelectModel.getSize(); i++) {
if (fontSelectModel.getElementAt(i).toString() == x) {
fontSelectModel.setSelectedItem(fontSelectModel.getElementAt(i));
}
}
}

// Font Size
public SpinnerModel getFontSizeModel() {
return fontSizeModel;
}

public int getFontSize() {
Integer i = (Integer)fontSizeModel.getValue();
return i.intValue();
}

public void setFontSize(int x) {
fontSizeModel.setValue(new Integer(x));
}
}
doubleoseven at 2007-11-11 22:35:20 >
# 2 Re: Initializing font in JTextPane
Here's the second half.

/** Presentation */
public class TextEditor extends JFrame {
private TE_Model teModel;

private JPanel mainPanel = new JPanel();
private JCheckBox myBoldButton = new JCheckBox("Bold");
private JCheckBox myItalicButton = new JCheckBox("Italic");
private JComboBox myFontSelect = new JComboBox();
private JSpinner myFontSize = new JSpinner();
private JTextPane myTextPane = new JTextPane();
private JButton myColorLabel = new JButton();

// Main - for testing
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}

// Create and show GUI - for testing
public static void createAndShowGUI() {
TextEditor te = new TextEditor();

te.setVisible(true);
te.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

// Constructor
public TextEditor() {
teModel = new TE_Model();

myBoldButton.setModel(teModel.getBoldButtonModel());
myItalicButton.setModel(teModel.getItalicButtonModel());

myFontSelect.setModel(teModel.getFontSelectModel());

myFontSize.setModel(teModel.getFontSizeModel());
myFontSize.setPreferredSize(new Dimension(40,25));

myColorLabel.setPreferredSize(new Dimension(20,20));

myTextPane.setStyledDocument(teModel.getStyledDocument());

JPanel lowerPanel = new JPanel();
lowerPanel.setLayout(new FlowLayout());
lowerPanel.add(myFontSize);
lowerPanel.add(myBoldButton);
lowerPanel.add(myItalicButton);
lowerPanel.add(myColorLabel);

JPanel controlsPanel = new JPanel();
controlsPanel.setLayout(new BoxLayout(controlsPanel, BoxLayout.Y_AXIS));
controlsPanel.setBorder(BorderFactory.createEtchedBorder());
controlsPanel.add(myFontSelect);
controlsPanel.add(lowerPanel);

mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
mainPanel.setPreferredSize(new Dimension(200, 275));
mainPanel.add(myTextPane);
mainPanel.add(controlsPanel);

this.initComponents();

this.setContentPane(mainPanel);
this.pack();
}

public JPanel getMainPanel() {
return mainPanel;
}

public StyledDocument getStyledDocument() {
return teModel.getStyledDocument();
}

public void setText(AttributedString x) {
teModel.setText(x);
}

public void isEnabled(boolean x) {
myTextPane.setEnabled(x);
}

// Get font list
private Vector getFonts() {
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontNames = env.getAvailableFontFamilyNames();

Vector fontlist = new Vector();
for (int i=0; i<fontNames.length; i++) {
fontlist.add(fontNames[i]);
}

return fontlist;
}

// Init component values
public void initComponents() {
// Font Select
teModel.addFonts(getFonts());
teModel.setFontSelection(0);

// Font Size
teModel.setFontSize(12);

// Color Label
myColorLabel.setBackground(Color.BLACK);

// TODO: Figure out why initial family value is not registered afterwards by CaretListener
// Init and disable text pane
SimpleAttributeSet attr = new SimpleAttributeSet();
StyleConstants.setBold(attr, false);
StyleConstants.setItalic(attr, false);
StyleConstants.setForeground(attr, Color.BLACK);
StyleConstants.setFontFamily(attr, "Arial");
StyleConstants.setFontSize(attr, 12);

StyleContext newContext = new StyleContext();
NamedStyle newStyle = newContext.new NamedStyle();
newStyle.addAttributes(attr);

myTextPane.setLogicalStyle(newStyle);

//isEnabled(false);

// Add event listeners
myBoldButton.addActionListener(new MyBoldButtonListener());
myItalicButton.addActionListener(new MyItalicButtonListener());
myFontSelect.addActionListener(new MyFontSelectListener());
myFontSize.addChangeListener(new MyFontSizeListener());
myColorLabel.addActionListener(new MyColorChangeListener());
myTextPane.addCaretListener(new MyCaretListener());
}

public void setTextPaneStyles(SimpleAttributeSet attributes) {
myTextPane.setCharacterAttributes(attributes, false);
}

public void setTextPaneFocus() {
myTextPane.requestFocus();
}

public void insertText(String text) {
int pos = myTextPane.getCaretPosition();
try {
teModel.getStyledDocument().insertString(pos, text, teModel.getCharacterStyles(pos).getAttributes());
}
catch (BadLocationException blx) {
System.out.println("Bad Location when inserting text");
}
}

public void addTextEditorKeyListener(KeyListener l) {
myTextPane.addKeyListener(l);
}

public void addTextEditorCaretListener(CaretListener l) {
myTextPane.addCaretListener(l);
}

public void addTextEditorBoldButtonListener(ActionListener l) {
myBoldButton.addActionListener(l);
}

public void addTextEditorItalicButtonListener(ActionListener l) {
myItalicButton.addActionListener(l);
}

public void addTextEditorFocusListener(FocusListener l) {
myTextPane.addFocusListener(l);
}

/** Listener classes */

// Toggle Bold Button state and set Text Pane input attributes accordingly
class MyBoldButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
teModel.toggleBoldButton();

SimpleAttributeSet attr = new SimpleAttributeSet();
StyleConstants.setBold(attr, teModel.getBoldButtonState());
setTextPaneStyles(attr);
setTextPaneFocus();
}
}

// Toggle Italic Button state and set Text Pane input attributes accordingly
class MyItalicButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
teModel.toggleItalicButton();

SimpleAttributeSet attr = new SimpleAttributeSet();
StyleConstants.setItalic(attr, teModel.getItalicButtonState());
setTextPaneStyles(attr);
setTextPaneFocus();
}
}

// Pop up color chooser and set color
class MyColorChangeListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
Color newColor = JColorChooser.showDialog(null, "Text Color", myColorLabel.getBackground());

if (newColor != null) {
myColorLabel.setBackground(newColor);

SimpleAttributeSet attr = new SimpleAttributeSet();
StyleConstants.setForeground(attr, newColor);
setTextPaneStyles(attr);
setTextPaneFocus();
}
}
}

// Change font face
class MyFontSelectListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
SimpleAttributeSet attr = new SimpleAttributeSet();
StyleConstants.setFontFamily(attr, teModel.getSelectedFontName());
setTextPaneStyles(attr);
setTextPaneFocus();
}
}

// Change font size
class MyFontSizeListener implements ChangeListener {
public void stateChanged(ChangeEvent e) {
SimpleAttributeSet attr = new SimpleAttributeSet();
StyleConstants.setFontSize(attr, teModel.getFontSize());
setTextPaneStyles(attr);
setTextPaneFocus();
}
}

// Get styles of character to the left of caret and set GUI style components accordingly
class MyCaretListener implements CaretListener {
public void caretUpdate(CaretEvent e) {
Element elem = teModel.getCharacterStyles(e.getDot()-1);
AttributeSet atts = elem.getAttributes();

teModel.setBoldButtonState(StyleConstants.isBold(atts));
teModel.setItalicButtonState(StyleConstants.isItalic(atts));
teModel.setFontSize(StyleConstants.getFontSize(atts));
myColorLabel.setBackground(StyleConstants.getForeground(atts));
teModel.setFontSelection(StyleConstants.getFontFamily(atts));
}
}

/** end listener classes */
}
doubleoseven at 2007-11-11 22:36:14 >