JTextPane font

Hi,
I'm trying to display a JTextPane that can change its font, characters size and style (bold/ italic/ underlined) by pressing a button.
I've tried using the method getAction of textPane and it works fine for changing the characters size and style but I can not change the font type this way, because Actions of JTextPane are very limited (only Serif, Monospaced and SansSerif.
Is there another way to change the font types?
I don't want to use setFont() of JTextPane because it changes the font of all of the text in the TextPane and I want to use different fonts on the text.
Thanks,
ofrit
ofrithaAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

allelopathCommented:
The O'Reilly swing book has an example a JTextPane with different fonts, maybe it will help you.

// StyleFrame.java
// A JTextPane with a menu for Style manipulation.

import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;

public class StyleFrame extends JFrame implements ActionListener {

  protected StyleBox styleBox;
  protected JTextPane textPane;
  protected JMenuBar menuBar;
  protected JMenu applyStyleMenu, modifyStyleMenu;
  protected JMenuItem createItem;

  public StyleFrame() {
    super("StyleFrame");

    styleBox = new StyleBox();
    textPane = new JTextPane();
    getContentPane().add(new JScrollPane(textPane), BorderLayout.CENTER);

    // set up menu
    menuBar = new JMenuBar();
    JMenu styleMenu = new JMenu("Style");
    menuBar.add(styleMenu);
    setJMenuBar(menuBar);

    applyStyleMenu = new JMenu("Set Logical Style");
    applyStyleMenu.setToolTipText(
        "set the Logical Style for the paragraph at caret location");
    styleMenu.add(applyStyleMenu);

    modifyStyleMenu = new JMenu("Modify Style");
    modifyStyleMenu.setToolTipText(
        "redefine a named Style (will affect paragraphs using that style)");
    styleMenu.add(modifyStyleMenu);

    createItem = new JMenuItem("Create New Style");
    createItem.setToolTipText(
        "define a new Style (which can then be applied to paragraphs)");
    createItem.addActionListener(this);
    styleMenu.add(createItem);

    // add the default style to applyStyleMenu and modifyStyleMenu
    createMenuItems(StyleContext.DEFAULT_STYLE);
  }

  protected void createMenuItems(String styleName) {
    // add 'styleName' to applyStyleMenu and modifyStyleMenu
    JMenuItem applyItem = new JMenuItem(styleName);
    applyItem.addActionListener(this);
    applyStyleMenu.add(applyItem);

    JMenuItem modifyItem = new JMenuItem(styleName);
    modifyItem.addActionListener(this);
    modifyStyleMenu.add(modifyItem);
  }

  public void actionPerformed(ActionEvent e) {
    // determine which menuItem was invoked and process it
    JMenuItem source = (JMenuItem)e.getSource();

    if ( applyStyleMenu.isMenuComponent(source) ) {
      // apply an existing style to the paragraph at the caret position
      String styleName = source.getActionCommand();
      Style style = textPane.getStyle(styleName);
      textPane.setLogicalStyle(style);
    }

    if ( source == createItem ) {
      // define a new Style and add it to the menus
      styleBox.clear();
      int response = JOptionPane.showConfirmDialog(this, styleBox,
          "Style Editor", JOptionPane.OK_CANCEL_OPTION,
          JOptionPane.PLAIN_MESSAGE);
      if (response == JOptionPane.OK_OPTION &&
styleBox.getStyleName().length() > 0) {
        String styleName = styleBox.getStyleName();
        Style style = textPane.addStyle(styleName, null);
        styleBox.fillStyle(style);
        createMenuItems(styleName); // add new Style to the menus
      }  
    }

    if ( modifyStyleMenu.isMenuComponent(source) ) {
      // redefine a Style (will automatically redraw paragraphs using Style)
      String styleName = source.getActionCommand();
      Style style = textPane.getStyle(styleName);
      styleBox.loadFromStyle(style);
      int response = JOptionPane.showConfirmDialog(this, styleBox,
          "Style Editor", JOptionPane.OK_CANCEL_OPTION,
          JOptionPane.PLAIN_MESSAGE);
      if (response == JOptionPane.OK_OPTION) styleBox.fillStyle(style);
    }
  }

  public static void main(String[] args) {
    JFrame frame = new StyleFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(400, 300);
    frame.setVisible(true);
  }
}
0
OviCommented:
       String name = "a - font - family";
        new StyledEditorKit.FontFamilyAction("font-family-" + name, name).actionPerformed('a dummy action event');
0
OviCommented:
will work on a selected text. The font family names are more that you are writing there, are all installed font families in the cient os.
0
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

ofrithaAuthor Commented:
Hi allelopath and Ovi,
I've tried your suggestions but did not manage to get the results I was looking for.

allelopath - The solution your code gives me is to change the font of all of the text and not just of the selected parts.

Ovi - I did not find a way to use your code.
Can you suggest a way to plant it in a program.

Thanks,
ofrit
0
OviCommented:
Just wait ...
0
OviCommented:
package tests.swing.text;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.StyledEditorKit;

public class ChangingFonts {
     public static void main(String[] args) {
          JFrame f = new JFrame();
          final JTextPane pane = new JTextPane();

          JPanel actions = new JPanel();
          String[] fArray = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
          final JComboBox fonts = new JComboBox(fArray);
          fonts.addActionListener(new ActionListener() {
               public void actionPerformed(ActionEvent ae) {
                    String name = fonts.getSelectedItem().toString();
                    new StyledEditorKit.FontFamilyAction("font-family-" + name, name).actionPerformed(ae);
                    pane.requestFocus();
               }
          });
          actions.add(new JLabel("Available fonts: "));
          actions.add(fonts);

          //  THIS IS WORKING TOO          
          //          JButton change = new JButton("Change");
          //          change.addActionListener(new ActionListener() {
          //               public void actionPerformed(ActionEvent ae) {
          //                    String name = fonts.getSelectedItem().toString();
          //                    new StyledEditorKit.FontFamilyAction("font-family-" + name, name).actionPerformed(ae);
          //                    pane.requestFocus();
          //               }
          //          });
          //          actions.add(change);

          Container c = f.getContentPane();
          c.setLayout(new BorderLayout());
          c.add(actions, BorderLayout.NORTH);
          c.add(new JScrollPane(pane), BorderLayout.CENTER);
          f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          f.setSize(600, 500);
          f.setVisible(true);
     }
}
0
ofrithaAuthor Commented:
Hi Ovi,
It worked great, but I have one problem with this solution.
I'm working with 2 JTextPanes and I need both of them to use the chosen font. I do not succeed to make them both refer to the font.
How do I link another JTextPane (for example pane2) to the font chosen in the JComboBox?
Thanks,
ofrit.
0
OviCommented:
wait a little ...
0
OviCommented:
package tests.swing.text;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.UIManager;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledEditorKit;

public class ChangingFonts {
      public static void main(String[] args) {
            JFrame f = new JFrame();
            final JTextPane pane1 = new JTextPane();
            final JTextPane pane2 = new JTextPane();
            final JTextPane pane3 = new JTextPane();
            final JTextPane pane4 = new JTextPane();
            final List editors = new ArrayList();
            editors.add(pane1);
            editors.add(pane2);
            editors.add(pane3);
            editors.add(pane4);
            final MultiEditorFontFamilyAction fontFamilyAction = new MultiEditorFontFamilyAction(editors, "", "");

            JPanel actions = new JPanel();
            String[] fArray = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
            final JComboBox fonts = new JComboBox(fArray);
            fonts.addActionListener(new ActionListener() {
                  public void actionPerformed(ActionEvent ae) {
                        String name = fonts.getSelectedItem().toString();
                        fontFamilyAction.setFamily("font-family-" + name, name);
                        fontFamilyAction.actionPerformed(ae);
//                        new StyledEditorKit.FontFamilyAction("font-family-" + name, name).actionPerformed(ae);
//                        pane.requestFocus();
                  }
            });
            actions.add(new JLabel("Available fonts: "));
            actions.add(fonts);
            
            JPanel editorsPanel = new JPanel();
            editorsPanel.setLayout(new GridLayout(1, 4, 5, 5));
            editorsPanel.add(new JScrollPane(pane1));
            editorsPanel.add(new JScrollPane(pane2));
            editorsPanel.add(new JScrollPane(pane3));
            editorsPanel.add(new JScrollPane(pane4));

            //  THIS IS WORKING TOO            
            //            JButton change = new JButton("Change");
            //            change.addActionListener(new ActionListener() {
            //                  public void actionPerformed(ActionEvent ae) {
            //                        String name = fonts.getSelectedItem().toString();
            //                        new StyledEditorKit.FontFamilyAction("font-family-" + name, name).actionPerformed(ae);
            //                        pane.requestFocus();
            //                  }
            //            });
            //            actions.add(change);

            Container c = f.getContentPane();
            c.setLayout(new BorderLayout());
            c.add(actions, BorderLayout.NORTH);
            c.add(editorsPanel, BorderLayout.CENTER);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setSize(600, 500);
            f.setVisible(true);
      }

}

class MultiEditorFontFamilyAction extends StyledEditorKit.FontFamilyAction {
      private List editorPanes;
      private String family;
      
      public MultiEditorFontFamilyAction(List editors, String nm, String family) {
            super(nm, family);
            editorPanes = editors;
            this.family = family;
      }
      
      public void setFamily(String nm, String family) {
            this.family = family;
            putValue(Action.NAME, nm);
      }

      public void actionPerformed(ActionEvent e) {
            for (int i = 0; i < editorPanes.size(); i++) {
                  JEditorPane editor = (JEditorPane) editorPanes.get(i);
                  if (editor != null) {
                        String family = this.family;
                        if ((e != null) && (e.getSource() == editor)) {
                              String s = e.getActionCommand();
                              if (s != null) {
                                    family = s;
                              }
                        }
                        if (family != null) {
                              MutableAttributeSet attr = new SimpleAttributeSet();
                              StyleConstants.setFontFamily(attr, family);
                              setCharacterAttributes(editor, attr, false);
                        } else {
                              UIManager.getLookAndFeel().provideErrorFeedback(editor);
                        }
                  }
            }
      }
}
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
OviCommented:
Note: the focus is not returning right now to the last edited  JtextPane. You should implement yourself the logic for managing focus via focus listeners to track the last one.
0
ofrithaAuthor Commented:
Hi Ovi,
Although your suggestion worked fine when I used it as is in a program (both in j2sdk 1.4.1 and JBuilder 1.2), when I tried to combine it to my program it gives me an error when using J2sdk 1.4.1 and when I use the JBuilder 1.2 it does not give me any error.
The error is:
java.lang.NullPointerException
at javax.swing.plaf.basic.BasicPopupMenuUI$MouseGrabber.grabContainer(BasicPopupMenuUI.java.344)

and so on...
Any idea why this error occurs on the jdk 1.4.1?

Thanks,
ofrit
0
OviCommented:
This is an error from your code, and not mine ... Try to look at how your menus are created and used. In which contextyou receive this error? When you click on a menu entry, when your application loads, etc.
0
ofrithaAuthor Commented:
Yes I know this error is in my code because when I ran only your code in the j2sdk 1.4.1 I did not get this error.
I get this error when I'm choosing one of the fonts in the JComboBox.
Compilation is fine and all other functions of the program works fine, but only when I try to use the combo box the error occurs.
Any suggestion will be welcome.
Thanks,
ofrit
0
OviCommented:
post the full stack trace, or the class where you use'it. Try to add a main(..) method to that class and test'it as standalone. I cannot debug yyour code if I cannot see'it, beside of the fact that debugging is not part and not related with the problem proposed in this question, neither to the solution.
0
ofrithaAuthor Commented:
Thank you very much for your help, I'll try finding the solution to the debugging problem.
ofrit
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Fonts Typography

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.