簡體   English   中英

作法:JTextPane自動換行不在文字邊界(例如“空格”)上,而是在字母邊界上

[英]How to: JTextPane auto wrapping NOT on word boundary such as “space”, but on letter boundary

我將JTextPane放入JScrollPane 正如我嘗試過的,如果JTextPane超出顯示區域的寬度,它將自動換行。 自動換行基於word boundary ,例如space字符。

我的內容包含很多space 我想literally顯示它。 所以,我需要自動換行,但我希望它發生ONLY在顯示區域的最大寬度, NOTword boundary

怎么樣?

我嘗試過的

  • 用'\\ 0'替換所有空格,因此從字面上看,我的內容是一個single big word

加1

以下是我在閱讀StanislavL的解決方案后的失敗嘗試。 我沒有責怪他的解決方案,因為我的情況與他的情況並不完全相同。

StanislavL的解決方案要求一行至少包含2個LabelView 據他介紹,這是Swinglayout()方法的實現所強加的, where forced break works only if row view has more than one child (請參閱: http : //java-sl.com/wrap.html )。 因此, StanislavL 特意\\r字符分配了一個特殊屬性,以確保單獨的LabelView 並將\\r用作包裝的界標 但是在我的場景中,我無法在內容中插入任何字符。

我的想法很簡單,只需為StyledEditorKit提供ViewFactory的自定義實現,因為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);
    }
}

此示例與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。 事實上,我們應該找到一個位置,我們可以打破GlyphView( this過去getBoundedPosition())。 p0表示Document中的char偏移量(GlyphView表示Character元素或Element的片段)。因此,想象一個很大的文本字符串。 在文檔中,它只是一個元素,因為它具有所有相同的屬性。 但是我們必須創建多個LabelView,因為文本片段太大而無法容納可用寬度。 因此,對於第一個標簽,p0為0。然后,對於下一個標簽,是一個偏移量,在該偏移量處,我們打破了最初的巨大視野。 如果我們再次打破它,那么另一個偏移量。 然后有2個參數僅代表容器的x移動和寬度(例如父視圖)。

因此,我們有一段很重要的文字,應該找到突破口。 當前方法更容易,因為我們不在乎優先級(空格與其他字符)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM