在Java6之前的所有版本中,放在JScrollPane中的JTextPane的默认行为是:如果可能,在单词边界处换行。如果没有,那么无论如何都要包装它们。
在JDK 7中,默认行为似乎是:如果可能,在单词边界处换行。如果不是,只需扩展JTextPane的宽度(不要换行过长的单词)。
这很容易重现,这是一个SSCCE:
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);
}
}
只需在JDK 6和JDK 7中运行它,编写一些小单词和一个长单词,您就会看到不同之处。
我的问题很简单。JDK 7中的新默认行为完全搞乱了我的一个程序(他们在Oracle更改这种默认行为时应该更加小心……它们看起来并不重要,但当您使用JTextPane显示通常包含非常长的字母字符串的数据时,它们并不是那么不重要-事实上,我将提交一份错误报告,但如果它们不能解决这个问题,我希望有一个解决办法)。有没有办法回到之前的行为?
请注意,我已经检查了相关问题How is word-wrapping implemented in JTextPane, and how do I make it wrap a string without spaces?的答案,但它并没有回答这个问题-它提供了一种使JTextPane换行而完全不考虑空格的方法,但对我来说,所需的行为是在可能的情况下在空格处分割线条,如果不可能的话在其他地方(如在以前的Java版本中)。
发布于 2012-11-14 17:08:14
对我来说,这个修复是有效的(在1.7.0_09下测试)
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);
}
}
}
}
发布于 2012-06-27 22:51:21
从@dk89捕捉到的不错,但遗憾的是,给定的变通方法不起作用:JDK7显然仍然不提供在JTextComponent上设置自定义BreakIterator的等待;甚至在GlyphView上也不提供,在GlyphView上,BreakIterator的生成是私有的。如果我们逐个字符地插入字符串char,它仍然不起作用:我假设具有相同样式(AttributeSet)的连续文本串折叠在一起。
我花了两天的时间尝试做一个自定义的EditorKit,就像其他地方建议的那样,但它并不像文本那样工作得很好(至少对于JDK 1.7.0_4 )。
我尝试了在How to word wrap text stored in JTextPanes which are cells in a JList给出的解决方案和在http://www.experts-exchange.com/Programming/Languages/Java/Q_20393892.html找到的一个变体
但我发现,当breakView小于句子中最长的单词时,将不再调用JTextPane。因此,当只有一个(长)单词时,它根本不起作用。这就是我们的情况,因为我们在相当小的空间中显示用户提供的类似标识符的字符串,通常没有空格。
我最终找到了一个简单的解决方案,源自bug报告中的建议:确实,逐个字符地插入字符串char,但要有不同的样式!因此,我们有和字符一样多的段,字符串被包装在字符的边界上。直到下一个"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);
}
正如bug中所述,它们应该提供一种简单的方法(可能是一些属性,或者一些可注入的东西)来恢复到旧的行为。
发布于 2011-12-29 23:19:20
https://stackoverflow.com/questions/8666727
复制相似问题