在JTextPane中包装长单词(Java 7)
在6之前的所有Java版本中,放在JScrollPane中的JTextPane的默认行为是:如果可能,在单词边界处换行。如果没有,那么无论如何都要把它们包起来 在JDK 7中,默认行为似乎是:如果可能,在单词边界处换行。如果没有,只需扩展JTextPane的宽度(不要包装长单词) 这很容易复制,这里是一个SSCCE:在JTextPane中包装长单词(Java 7),java,swing,word-wrap,java-7,jtextpane,Java,Swing,Word Wrap,Java 7,Jtextpane,在6之前的所有Java版本中,放在JScrollPane中的JTextPane的默认行为是:如果可能,在单词边界处换行。如果没有,那么无论如何都要把它们包起来 在JDK 7中,默认行为似乎是:如果可能,在单词边界处换行。如果没有,只需扩展JTextPane的宽度(不要包装长单词) 这很容易复制,这里是一个SSCCE: public class WrappingTest extends JFrame { public static void main ( String[] args )
public class WrappingTest extends JFrame
{
public static void main ( String[] args )
{
new WrappingTest();
}
public WrappingTest ()
{
setSize(200,200);
getContentPane().setLayout(new BorderLayout());
JTextPane jtp = new JTextPane();
JScrollPane jsp = new JScrollPane(jtp);
jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
getContentPane().add(jsp,BorderLayout.CENTER);
setVisible(true);
}
}
只需在JDK6和JDK7中运行它,写一些小词,然后写一个长词,您就会看到区别
我的问题很简单。。。JDK 7中新的默认行为完全扰乱了我的程序(在Oracle更改此类默认值时,他们应该更加小心……它们似乎不重要,但当您使用JTextPane显示通常包含很长字符串的数据时,它们并不是那么不重要——事实上,我将提交一份错误报告,但如果他们不解决它,我希望有一个解决方法).有没有办法回到以前的行为
请注意,我已经检查了相关问题的答案,但它没有回答这个问题-它提供了一种使JTextPane包装的方法,完全不考虑空格,但对我来说,所需的行为是在空格处拆分行(如果可能),在其他地方拆分行(如以前的Java版本).看看这个bug:
嗨,我也遇到了同样的问题,但找到了解决办法: 只需创建JTextPane的扩展类,例如
MyWrapJTextPane extends JTextPane
并覆盖以下方法-有效;-)
来自@dk89的好消息,但遗憾的是,给定的解决方法不起作用:JDK 7显然仍然没有等待在JTextComponent上设置自定义BreakIterator;即使在GlyphView上也不行,因为BreakIterator的生成是私有的。如果我们一个字符一个字符地插入字符串,它仍然不起作用:我假设具有相同样式的连续文本(AttributeSet)被折叠在一起 我花了两天的时间尝试编写一个定制的EditorKit,正如其他地方所建议的那样,但它不能很好地作为文本使用(至少使用JDK1.7.0_4) 我尝试了在中给出的解决方案,并在中找到了一个变体 但是我发现当JTextPane小于句子中最长的单词时,不再调用breakView。因此,当只有一个(长)单词时,它根本不起作用。这就是我们的情况,当我们在很小的空间中显示用户提供的、类似标识符的字符串时,通常没有空格 我终于找到了一个简单的解决方案,这个解决方案来源于bug报告中的建议:确实,逐字符插入字符串,但要使用其他样式!因此,我们有和字符一样多的段,字符串被包装在字符边界上。直到下一个“bug修复” 代码片段:
private JTextPane tp;
private SimpleAttributeSet sas = new SimpleAttributeSet();
tp= new JTextPane();
sas.addAttribute( "A", "C" ); // Arbitrary attribute names and value, not used actually
// Set the global attributes (italics, etc.)
tp.setParagraphAttributes(styleParagraphAttributes, true);
Document doc = tp.getDocument();
try
{
doc.remove(0, doc.getLength()); // Clear
for (int i = 0; i < textToDisplay.length(); i++)
{
doc.insertString(doc.getLength(), textToDisplay.substring(i, i+1),
// Change attribute every other char
i % 2 == 0 ? null : sas);
}
}
catch (BadLocationException ble)
{
log.warn("Cannot happen...", ble);
}
私有jtextp;
私有SimpleAttributeSet sas=新SimpleAttributeSet();
tp=新的JTextPane();
sas.addAttribute(“A”、“C”);//任意属性名称和值,实际未使用
//设置全局属性(斜体等)
tp.setParagraphAttributes(styleParagraphAttributes,true);
Document doc=tp.getDocument();
尝试
{
doc.remove(0,doc.getLength());//清除
对于(int i=0;i
正如bug中所述,他们应该提供一种简单的方法(可能是一些属性,或者一些可注入的东西)来恢复旧的行为。对我来说,修复程序是有效的(在1.7.0\u 09下测试)
使用有帮助吗?我也有同样的问题。相关:(没有答案…)那里的海报已经创建了一个bug报告,但它被关闭为“不是bug”,没有任何解释…谢谢,它非常相似。。。但不幸的是,这似乎不是同一个bug(它与属性集有关,很久以前就被修复了):/我认为这是相关的,尽管1.6中的行为没有改变。请看评论:“应该注意,请求的默认拆分行为(当BreakIterator找不到有效断点时,在任意位置中断GlyphView)是非常错误的,不应该在任何JDK版本中恢复,无论是将来还是过去。”看起来我们现在需要做更多的工作……抱歉:不可以!这只解决了长行(包含空格)的问题——它们现在被正确地包装了——但是长词仍然没有被包装:-(实际上我们需要的是让getMinimumSpan()对于X_轴,LabelView返回0。ViewFactory是一种替换默认LabelViewAach的方法,我可以看到并获得它,谢谢,非常正确地用于
jtp.setComponentOrientation(RTL);
Too我们如何解决jtp.setEditorKit(新的WrapEditorKit())行中的强制转换问题;?我得到一个javax.swing.text.DefaultStyledDocument不能转换为该行中的javax.swing.text.html.HTMLDocument。您使用另一个编辑器工具包。猜测HTMLEditorKit。对该工具包执行相同的操作。
private JTextPane tp;
private SimpleAttributeSet sas = new SimpleAttributeSet();
tp= new JTextPane();
sas.addAttribute( "A", "C" ); // Arbitrary attribute names and value, not used actually
// Set the global attributes (italics, etc.)
tp.setParagraphAttributes(styleParagraphAttributes, true);
Document doc = tp.getDocument();
try
{
doc.remove(0, doc.getLength()); // Clear
for (int i = 0; i < textToDisplay.length(); i++)
{
doc.insertString(doc.getLength(), textToDisplay.substring(i, i+1),
// Change attribute every other char
i % 2 == 0 ? null : sas);
}
}
catch (BadLocationException ble)
{
log.warn("Cannot happen...", ble);
}
import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
public class WrapTestApp extends JFrame {
public static void main ( String[] args ) {
new WrapTestApp();
}
public WrapTestApp () {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(200,200);
getContentPane().setLayout(new BorderLayout());
JTextPane jtp = new JTextPane();
jtp.setEditorKit(new WrapEditorKit());
JScrollPane jsp = new JScrollPane(jtp);
jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
getContentPane().add(jsp, BorderLayout.CENTER);
jtp.setText("ExampleOfTheWrapLongWordWithoutSpaces");
setVisible(true);
}
class WrapEditorKit extends StyledEditorKit {
ViewFactory defaultFactory=new WrapColumnFactory();
public ViewFactory getViewFactory() {
return defaultFactory;
}
}
class WrapColumnFactory implements ViewFactory {
public View create(Element elem) {
String kind = elem.getName();
if (kind != null) {
if (kind.equals(AbstractDocument.ContentElementName)) {
return new WrapLabelView(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);
}
}
// default to text display
return new LabelView(elem);
}
}
class WrapLabelView extends LabelView {
public WrapLabelView(Element elem) {
super(elem);
}
public float getMinimumSpan(int axis) {
switch (axis) {
case View.X_AXIS:
return 0;
case View.Y_AXIS:
return super.getMinimumSpan(axis);
default:
throw new IllegalArgumentException("Invalid axis: " + axis);
}
}
}
}