如何:JTextPane自动包装不在单词边界,如“空格”,但在字母边界

时间:2015-05-28 08:31:28

标签: java swing jscrollpane jtextpane

我将JTextPane放入JScrollPane。正如我所尝试的那样,如果JTextPane超出显示区域的宽度,word boundary将自动换行。自动换行基于space,例如space个字符。

我的内容包含大量literally。我想显示它ONLY。所以我需要自动换行,但我希望它在显示区域的最大宽度NOT word boundary single big word上发生StanislavL

如何?

我尝试过:

  • 将所有空格替换为'\ 0',从字面上看,我的内容为LabelView

ADD 1

在阅读StanislavL's solution后,我的失败尝试在下面。 我并没有责怪他的解决方案,因为我的情景与他的情况并不完全相同。

Swing的解决方案要求一行包含至少2 layout()个。据他说,这是where forced break works only if row view has more than one child实施StanislavL方法\r所强加的(见http://java-sl.com/wrap.html)。因此,LabelView 故意\r字符分配了一个特殊属性,以确保单独的ViewFactory。并使用StyledEditorKit作为包装的地标。但在我的场景中,我无法在我的内容中插入任何字符。

我的想法很简单,只需为ViewFactory提供this.jTextPane.setEditorKit(new StyledEditorKit(){ @Override public ViewFactory getViewFactory(){ return new LetterWrappingStyledViewFactory(maxCharWidth); } }); 的自定义实现,因为ViewFactory界面决定了分数权重以及如何发生中断:

public class LetterWrappingStyledViewFactory implements ViewFactory {


    public int maxCharWidth = -1; // this is the max width where I want wrap to happen.

    public LetterWrappingStyledViewFactory(int maxCharWidth) {
        this.maxCharWidth = maxCharWidth;
    }

    public View create(Element elem) {
        String kind = elem.getName();
        if (kind != null) {
            if (kind.equals(AbstractDocument.ContentElementName)) {
                return new LabelView(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 > maxCharWidth)
                                return View.ForcedBreakWeight;
                            else
                                return View.BadBreakWeight;
                        }
                        return super.getBreakWeight(axis, pos, len);
                    }

                    public View breakView(int axis, int p0, float pos, float len) {
                        if (axis == View.X_AXIS) {
                            checkPainter();
                            int p1 = getGlyphPainter().getBoundedPosition(this, p0, pos, len);
                            if (p0 == getStartOffset() && p1 <= maxCharWidth) {
                                return this;
                            }
                            return createFragment(p0, maxCharWidth);
                        }
                        return this;
                    }
                };
            } 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);
    }
}

以下是我对接口$loop = getUsersHoursDetail("2015-05-04","2015-05-26","3"); $new_posts = array(); $merged = array(); foreach($loop as $post) { $week = date('W', strtotime($post['dt'])); $year = date('Y', strtotime($post['dt'])); $week_start = new DateTime(); $week_start->setISODate($year,$week); if( !isset($new_posts[$week_start->format('Y-m-d')]) ) { $new_posts[$week_start->format('Y-m-d')] = array(); } $date = $post['dt']; if (!isset($merged[$date])) { $merged[$date] = array(); } array_push($merged[$date], $post); $new_posts[$week_start->format('Y-m-d')] = $merged; } 的实现:

'&', 'variable name' , '='

1 个答案:

答案 0 :(得分:3)

此示例适用于StyledEditorKit(使用java 7测试)

import javax.swing.*;
import javax.swing.text.*;


public class WrapApp extends JFrame {
    JEditorPane edit=new JEditorPane();
    public WrapApp() {
        super("Wrap in the mid");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        edit.setEditorKit(new WrapEditorKit());
        edit.setText("111 222 333333333333333333333333333333333333333333333");

        getContentPane().add(new JScrollPane(edit));
        setSize(200,200);
        setLocationRelativeTo(null);
    }

    public static void main(String[] args) {
        WrapApp m = new WrapApp();
        m.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 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;
            }
            return View.GoodBreakWeight;
        }
        return super.getBreakWeight(axis, pos, len);
    }
    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);
        }
    }

    public View breakView(int axis, int p0, float pos, float len) {
        if (axis == View.X_AXIS) {
            checkPainter();
            int p1 = getGlyphPainter().getBoundedPosition(this, p0, pos, len);
            GlyphView v = (GlyphView) createFragment(p0, p1);
            return v;
        }
        return super.breakView(axis, p0, pos, len);
    }
}

更新:

关于GlyphPainter。事实上,我们应该找到一个位置,我们可以在getBoundedPosition()中打破GlyphView(this过去。 p0表示Document中的char偏移量(GlyphView表示Element的元素或片段)) 想象一下大量的文字。在文档中,它只是一个元素,因为它具有所有相同的属性。但我们必须创建多个LabelView,因为文本片段太大而无法容纳可用宽度。因此,对于第一个标签,p0为0.然后,对于下一个标签,我们打破了我们最初的巨大视图。如果我们再次打破它,那么另一个偏移。然后是2个参数,只代表x shift和容器的widht(例如父视图)。

所以我们有一个大文本,应该找到打破的地方。目前的方式更容易,因为我们不关心优先级(空格与其他字符)。