I have a JTextPane
whose model is a DefaultStyledDocument
. I'm noticing that if the text is displayed, and I then use setCharacterAttributes
to change every character on a line to a much larger font, the font of the characters on that line is changed in the display as I expect, but the lines below it don't move, so that the lines overlap in the display.
Is there a way to force the JTextPane
to recompute the text locations and redisplay itself (or a portion of itself)? I tried setting up a DocumentListener
with changedUpdate
, and changedUpdate
is indeed called, but I can't find a way to make it redraw the JTextPane
. revalidate()
didn't work.
EDIT: The lines do shift by themselves with a smaller test case, so apparently something else I'm doing in the program is interfering, but I haven't figured out what. Anyway, repaint()
without revalidate()
works if I can't determine what feature is causing a problem and how to get around it.
EDIT 2: The problem occurs when the JTextPane is added to a JPanel and the JPanel is set up with BoxLayout
and BoxLayout.X_AXIS
. A sample:
public class Demo extends JFrame {
JPanel panel;
JTextPane textPane;
DefaultStyledDocument doc;
SimpleAttributeSet smallText, bigText;
public Demo() {
super("Demo");
doc = new DefaultStyledDocument ();
textPane = new JTextPane(doc);
panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
// problem goes away if above line is removed
panel.add(textPane);
panel.setPreferredSize(new Dimension(1000, 500));
textPane.setCaretPosition(0);
textPane.setMargin(new Insets(5,5,5,5));
getContentPane().add(panel, BorderLayout.CENTER);
smallText = new SimpleAttributeSet();
StyleConstants.setFontFamily(smallText, "SansSerif");
StyleConstants.setFontSize(smallText, 16);
bigText = new SimpleAttributeSet();
StyleConstants.setFontFamily(bigText, "Times New Roman");
StyleConstants.setFontSize(bigText, 32);
initDocument();
textPane.setCaretPosition(0);
}
protected void initDocument() {
String initString[] =
{ "This is the first line.",
"This is the second line.",
"This is the third line." };
for (int i = 0; i < initString.length; i ++) {
try {
doc.insertString(doc.getLength(), initString[i] + "\n",
smallText);
} catch (BadLocationException e) {
}
}
}
private void createAndShowGUI() throws InterruptedException {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public static void main(String[] args) throws Exception {
new Demo().runMain();
}
private void runMain() throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
UIManager.put("swing.boldMetal", Boolean.FALSE);
try {
createAndShowGUI();
} catch (InterruptedException e) {
}
}
});
Thread.sleep(2000);
doc.setCharacterAttributes(24, 24, bigText, false);
}
}
Call repaint()
it will redraw the container. DocumentListener
reflects changes to a text document, so in your case is inappropriate. You can use DefaultStyledDocument.getStyle().addChangeListener()
to handle changes of the attributes.