Java Forum / GUI / March 2007
JTextPane line wrap change in windows JRE 1.5.0_10?
reinhard.engels@gmail.com - 14 Mar 2007 18:04 GMT For several years, I've been displaying marked up DNA and RNA in a JTextPane. It's worked great. I can mark up interesting substrings with different fonts or background colors and it wraps like you'd expect -- at the edge of the component.
All of a sudden, users with the latest JRE on windows (1.5.0_10) are seeing line breaks at at what looks like "style change" points. It's as if instead of breaking at the character closest to the edge of the component, the JTextPane now in this version thinks it can break at "style boundaries."
Screenshots here showing how my app looks in jar 1.5.0_4 (good) and 1.5.0_10 (bad):
http://everydaysystems.com/usenet/JTextPane/
Is this a bug in the new release of JTextPane? Or is this an intentional new feature? I can't find anything about it. As I mentioned, all previous versions of the JRE I have access to on PCs and mac work fine, it's just windows jre version 1.5.0_10.
Fingers crossed that this is a bug that will be quickly fixed by sun because everything I've found on manually overriding JTextPane line breaking sounds like a nightmare...
Many thanks in advance to anyone who takes a look at this!
Reinhard
reinhard.engels@gmail.com - 14 Mar 2007 21:13 GMT Below is a simple code sample illustrating the problem.
When I run this code on my mac with jre 1.5.0_7 and on my pc with jre 1.5.0_4 lines are wrapped chunked by character. This is exactly what I want and it makes sense.
But when I run this code on my pc with jre 1.5.0_10 lines are wrapped chunked by AttributeSet "style." I can't see how this is not a bug... but perhaps I'm missing something.
import java.awt.Color; import java.awt.Font;
import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTextPane; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import javax.swing.text.MutableAttributeSet; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants;
public class JTextPaneWrapChangeDemo {
public JTextPaneWrapChangeDemo() { super(); }
public static void main(String[] args) { JTextPaneWrapChangeDemo demo = new JTextPaneWrapChangeDemo(); demo.run(); }
public void run() { JFrame frame = new JFrame(); frame.setSize(400, 400); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JTextPane textPane = new JTextPane(); JScrollPane scrollPane = new JScrollPane(textPane); frame.add(scrollPane); textPane.setEditable(false); textPane.setFont(new Font("Courier", Font.PLAIN, 12)); MutableAttributeSet exonAttributeSet = new SimpleAttributeSet(); MutableAttributeSet intronAttributeSet = new SimpleAttributeSet(); StyleConstants.setFontSize(exonAttributeSet, 12); StyleConstants.setForeground(exonAttributeSet, Color.blue); StyleConstants.setFontSize(intronAttributeSet, 12); StyleConstants.setForeground(intronAttributeSet, Color.black); try { Document d = textPane.getDocument(); d.insertString(d.getLength(), exon1, exonAttributeSet); d.insertString(d.getLength(), intron1, intronAttributeSet); d.insertString(d.getLength(), exon2, exonAttributeSet); d.insertString(d.getLength(), intron2, intronAttributeSet); d.insertString(d.getLength(), exon3, exonAttributeSet);
} catch (BadLocationException e) { System.out.println("bad location exception" + e); } frame.show(); }
String exon1 = "ATGCCACCAAAAGCGCGTATAAACTCAAAAAATTCAGTTGAGCAGGAGGGAAGGGTCCTACTTGCAGTATCAGCTTTGAAAAATAAGGAAATTCTCAATATTCGTGAAGCTGCGCGTGTCTATAATGTGCCTTATACTACCCTCCAGCGGCGCCTAAAGGGGCATACTTTTCGAGCTGAATTACGCGCAAATGGCCATAAAATGACTCAGAATGAAGAGGATTCACTTATTAGATGGATTCTATCTATGGATCAACGTGGAGCGGCTCCCCGACCGTCCCATGTACGAGAAATGGCGAATATCCTGCTTGCGCAGCGTGGTTCAACTCCTACCCAGACTGTTGGAGAGAAATGGGTATATAACTTCATTAATCGGCATGATGAGATCAAAACCCGATTCTCTAGGCGCTATAACCACCAGCGTGCTAAATGTGAAGACCCAAAGATTATCCTGGAATGGTTCAATCGTGTCCAGATCACAATAATGCAGCATGGGATTACACTGGAAGATATCTACAACTTTGATGAAACTGGCTTTGCAATGGGCTTAGTAGCTACTGCTAAG"; String intron1 = "GTAGTTACAAGAGCTGAGATGCTTAGTCGGCCCTTCCTTATCCAGCCAGGGAACCGCGAATGGGTTACCTCTATAGAGTGTATTAACTCTACTGGCTGGGTGCTTCCACCATGCATTATCTTCAAGGGAAAGGTCCATATTGAGGACTGGTATTAAGATACAGCCTTACCAGCAGACTGGCGGATCGAGGTCAGTGAGAATGGATGGACGACTGATCAGATTGGATTACGATGGCTTCAAAAAGTCTTTATTCCTGCTACTACCAGTCGTACAACTGGTAGATATCGACTATTAATTCTTGATGGCCATGGGAGCCATCTAACACCACAGTTTGATCAAATCTGCACTGAGAATGATATCATTCCAATCTGCATGCCTGCACATTCATCACATCTCCTCCAGCCTCTAGATGTTGGCTGTTTCTCTCCTCTTAAGCGTGCGTATGGCCGCTTGATTGAGGATAAGATGCGGCTTGGTTTCAACCATATTGACAAGTTTGATTTCCTTGAGGCCTATCCACAAGCTCATACGGCAATCTTTTCAGCAGATAATATTAAAAGTGGCTTTTCAGCAACTGGATTAATACCACTGAATCCAGATCGGGTGCTCAGTCAGCTTAATATCCAGCTTAGAACACCTACACCACCAGGCAGCCGATCAACTAATTCTGTCCCAAAAACACCTTACAATCTCAAGCA"; String exon2 = "GCTGAAGAAGCAGGAAACTACGCTTAAGAAGCTACTTAGGGAGCGTACATACAGCCCTCCTACCCCTACAAAGGCTGTGCTAGGTCAGATTATCAAGGGGTGTGAGATGGCAATGAATAACGCTGCCCTTCTTGCAAAGGAAAATCATGATCTACGTGCTGCACATGAAAAGCACCTTCAAAAGCAGAAGCGATCTAGGCGGCAGATAGAAACTGCA"; String intron2 = "GTGGGATTATCTATCCAGGAAGGGCAGGAGATCATTTAACGCAGGGATCAGGCTGCTGAAGCTATCCCAACTATCCCTCCAGAGCAGGTAGTAGATACAGAACAACGCCCTCAACGGGCACCCCCACGCTGCAGTGACTGCCATATTCTAGGCCATAGGCGATTGCAATGTCCGCAGCGCAAGAATAACTAGATTTAGTAATAAAATCATGTTTTAGGGGTTCAAAATAGCCTCCAATTTCGGCCGCGGCCAAATTCTATAG"; String exon3 = "TATGGTGATCCGCTCGGTTACGTGATCCGCTCGCTTACCGATTACGTTACTTCTCTGGAAGACGATCCTGGACTAAGTCATTTCCTTTTGCGTAGTTCAGCGGATTTTTTTTTTCTTCTGCTACTTGGGGTCGCTGAAGATGGAATCAATCAGACGT";
}
Larry Barowski - 15 Mar 2007 15:21 GMT > For several years, I've been displaying marked up DNA and RNA in a > JTextPane. It's worked great. I can mark up interesting substrings [quoted text clipped - 6 lines] > component, the JTextPane now in this version thinks it can break at > "style boundaries." I can confirm the bug, and that it doesn't happen in 1.5.0_09. It looks similar to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4948033 The example in that bug report also shows incorrect line breaks under newer versions of Java when the i18n property is false, though the incorrect breaks are not exactly the same as with i18n true. I suggest that you report this as a new bug.
As far as a solution to your problem goes, you may need to lock your users into a specific version of Java, or go looking for a JTextPane replacement.
reinhard.engels@gmail.com - 15 Mar 2007 17:38 GMT Thanks for taking a look at this, Larry! And determining that it behaves properly up to 1.5.0_9.
I submitted a bug report to sun, but supposedly it'll take 3 weeks for them to even look at it.
Since most of my users aren't on this version of the jre yet, short term I guess I can get away with warning against 1.5.0_10...
I'll post any updates to this thread.
Reinhard
> I can confirm the bug, and that it doesn't happen in 1.5.0_09. > It looks similar tohttp://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4948033 [quoted text clipped - 6 lines] > lock your users into a specific version of Java, or go looking > for a JTextPane replacement. reinhard.engels@gmail.com - 28 Mar 2007 21:10 GMT 1. Sun officially acknowledged that this is a bug (see below). It also appears in jre version 1.6.
2. I have a workaround (see far below). With this workaround the wrapping behavior seems to work like it used to even on new versions of the JRE.
************************ From Sun ******************************
Hi Reinhard Engels,
Thank you for reporting this issue.
We have determined that this report is a new bug and entered the bug into our internal bug tracking system under Bug Id: 6539700.
You can monitor this bug on the Java Bug Database at http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6539700.
It may take a day or two before your bug shows up in this external database. As you are a member of the Sun Developer Network (SDN), there are two additional options once the bug is visible.
1. Voting for the bug Click http://bugs.sun.com/bugdatabase/addVote.do?bug_id=6539700.
2. Adding the report to your Bug Watch list. You will receive an email notification when this bug is updated. Click http://bugs.sun.com/bugdatabase/addBugWatch.do?bug_id=6539700.
SDN members can obtain fully licensed Java IDEs for web and enterprise development. More information is at http://developers.sun.com/prodtech/javatools/free/.
We greatly appreciate your efforts in identifying areas in the J2SE where we can improve upon and I would request you to continue doing so.
************************ End From Sun ******************************
************************ The workaround (same code as previously posted, plus an (inner) subclass of StyledEditorKit) ************
import java.awt.Color; import java.awt.Font;
import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTextPane; import javax.swing.text.AbstractDocument; import javax.swing.text.BadLocationException; import javax.swing.text.BoxView; import javax.swing.text.ComponentView; import javax.swing.text.Document; import javax.swing.text.Element; import javax.swing.text.IconView; import javax.swing.text.LabelView; import javax.swing.text.MutableAttributeSet; import javax.swing.text.ParagraphView; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; import javax.swing.text.StyledEditorKit; import javax.swing.text.View; import javax.swing.text.ViewFactory;
public class JTextPaneWrapChangeDemo {
public JTextPaneWrapChangeDemo() { super(); }
public static void main(String[] args) { JTextPaneWrapChangeDemo demo = new JTextPaneWrapChangeDemo(); demo.run(); }
public void run() { JFrame frame = new JFrame(); frame.setSize(400, 400); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JTextPane textPane = new JTextPane(); JScrollPane scrollPane = new JScrollPane(textPane); frame.add(scrollPane); textPane.setEditable(false); textPane.setEditorKit(new BioSequenceStyledEditorKit()); textPane.setFont(new Font("Courier", Font.PLAIN, 12)); MutableAttributeSet exonAttributeSet = new SimpleAttributeSet(); MutableAttributeSet intronAttributeSet = new SimpleAttributeSet(); StyleConstants.setFontSize(exonAttributeSet, 12); StyleConstants.setForeground(exonAttributeSet, Color.blue); StyleConstants.setFontSize(intronAttributeSet, 12); StyleConstants.setForeground(intronAttributeSet, Color.black); try { Document d = textPane.getDocument(); d.insertString(d.getLength(), exon1, exonAttributeSet); d.insertString(d.getLength(), intron1, intronAttributeSet); d.insertString(d.getLength(), exon2, exonAttributeSet); d.insertString(d.getLength(), intron2, intronAttributeSet); d.insertString(d.getLength(), exon3, exonAttributeSet);
} catch (BadLocationException e) { System.out.println("bad location exception" + e); } frame.show(); }
String exon1 = "ATGCCACCAAAAGCGCGTATAAACTCAAAAAATTCAGTTGAGCAGGAGGGAAGGGTCCTACTTGCAGTATCAGCTTTGAAAAATAAGGAAATTCTCAATATTCGTGAAGCTGCGCGTGTCTATAATGTGCCTTATACTACCCTCCAGCGGCGCCTAAAGGGGCATACTTTTCGAGCTGAATTACGCGCAAATGGCCATAAAATGACTCAGAATGAAGAGGATTCACTTATTAGATGGATTCTATCTATGGATCAACGTGGAGCGGCTCCCCGACCGTCCCATGTACGAGAAATGGCGAATATCCTGCTTGCGCAGCGTGGTTCAACTCCTACCCAGACTGTTGGAGAGAAATGGGTATATAACTTCATTAATCGGCATGATGAGATCAAAACCCGATTCTCTAGGCGCTATAACCACCAGCGTGCTAAATGTGAAGACCCAAAGATTATCCTGGAATGGTTCAATCGTGTCCAGATCACAATAATGCAGCATGGGATTACACTGGAAGATATCTACAACTTTGATGAAACTGGCTTTGCAATGGGCTTAGTAGCTACTGCTAAG"; String intron1 = "GTAGTTACAAGAGCTGAGATGCTTAGTCGGCCCTTCCTTATCCAGCCAGGGAACCGCGAATGGGTTACCTCTATAGAGTGTATTAACTCTACTGGCTGGGTGCTTCCACCATGCATTATCTTCAAGGGAAAGGTCCATATTGAGGACTGGTATTAAGATACAGCCTTACCAGCAGACTGGCGGATCGAGGTCAGTGAGAATGGATGGACGACTGATCAGATTGGATTACGATGGCTTCAAAAAGTCTTTATTCCTGCTACTACCAGTCGTACAACTGGTAGATATCGACTATTAATTCTTGATGGCCATGGGAGCCATCTAACACCACAGTTTGATCAAATCTGCACTGAGAATGATATCATTCCAATCTGCATGCCTGCACATTCATCACATCTCCTCCAGCCTCTAGATGTTGGCTGTTTCTCTCCTCTTAAGCGTGCGTATGGCCGCTTGATTGAGGATAAGATGCGGCTTGGTTTCAACCATATTGACAAGTTTGATTTCCTTGAGGCCTATCCACAAGCTCATACGGCAATCTTTTCAGCAGATAATATTAAAAGTGGCTTTTCAGCAACTGGATTAATACCACTGAATCCAGATCGGGTGCTCAGTCAGCTTAATATCCAGCTTAGAACACCTACACCACCAGGCAGCCGATCAACTAATTCTGTCCCAAAAACACCTTACAATCTCAAGCA"; String exon2 = "GCTGAAGAAGCAGGAAACTACGCTTAAGAAGCTACTTAGGGAGCGTACATACAGCCCTCCTACCCCTACAAAGGCTGTGCTAGGTCAGATTATCAAGGGGTGTGAGATGGCAATGAATAACGCTGCCCTTCTTGCAAAGGAAAATCATGATCTACGTGCTGCACATGAAAAGCACCTTCAAAAGCAGAAGCGATCTAGGCGGCAGATAGAAACTGCA"; String intron2 = "GTGGGATTATCTATCCAGGAAGGGCAGGAGATCATTTAACGCAGGGATCAGGCTGCTGAAGCTATCCCAACTATCCCTCCAGAGCAGGTAGTAGATACAGAACAACGCCCTCAACGGGCACCCCCACGCTGCAGTGACTGCCATATTCTAGGCCATAGGCGATTGCAATGTCCGCAGCGCAAGAATAACTAGATTTAGTAATAAAATCATGTTTTAGGGGTTCAAAATAGCCTCCAATTTCGGCCGCGGCCAAATTCTATAG"; String exon3 = "TATGGTGATCCGCTCGGTTACGTGATCCGCTCGCTTACCGATTACGTTACTTCTCTGGAAGACGATCCTGGACTAAGTCATTTCCTTTTGCGTAGTTCAGCGGATTTTTTTTTTCTTCTGCTACTTGGGGTCGCTGAAGATGGAATCAATCAGACGT";
class BioSequenceStyledEditorKit extends StyledEditorKit {
ViewFactory defaultFactory = new WrapColumnFactory();
public ViewFactory getViewFactory() { return defaultFactory; }
public BioSequenceStyledEditorKit() { super(); }
class BioSequenceLabelView extends LabelView { public BioSequenceLabelView(Element elem) { super(elem); }
public int getBreakWeight(int axis, float pos, float len) { if (axis == View.X_AXIS) { checkPainter(); int p0 = getStartOffset(); int p1 = getGlyphPainter().getBoundedPosition(this, p0, pos, len); if (p1 == p0) { // can't even fit a single character return View.BadBreakWeight; } // if (getBreakSpot(p0, p1) != -1) { // return View.ExcellentBreakWeight; // } // Nothing good to break on. return View.GoodBreakWeight; } return super.getBreakWeight(axis, pos, len); } }
class WrapColumnFactory implements ViewFactory { public View create(Element elem) { String kind = elem.getName(); if (kind != null) { if (kind.equals(AbstractDocument.ContentElementName)) { return new BioSequenceLabelView(elem); } else if (kind .equals(AbstractDocument.ParagraphElementName)) { return new ParagraphView(elem); } else if (kind.equals(AbstractDocument.SectionElementName)) { return new BoxView(elem, View.Y_AXIS); } else if (kind.equals(StyleConstants.ComponentElementName)) { return new ComponentView(elem); } else if (kind.equals(StyleConstants.IconElementName)) { return new IconView(elem); } } return new LabelView(elem); } }
}
}
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|