4

だから、私はこのJTexrtAreaを持っています。これは私のニーズにほぼ完璧です。唯一の問題は、行の間隔です。設定できません。(なぜJTextPaneではないのですか?JTextAreaでは間隔を変更でき、JTextAreaはJTextPaneよりもはるかに軽量であり、プログラムにはそれらがたくさんあります)。

私は以前にこの質問をしました、そしてこれは私がユーザーStanislavLから得た答えです:


JTextAreaの行間隔を上書きするには、PlainView(PLainDocumentのレンダリングに使用)を確認してください。

public void paint(Graphics g、Shape a)メソッドには次の行があります

    drawLine(line, g, x, y);
    y += fontHeight;

したがって、yオフセットを固定してレンダリングを調整できます。

BasicTextAreaUIメソッドでビューを作成します。それをPlainViewの独自の実装に置き換えます

public View create(Element elem) {
Document doc = elem.getDocument();
Object i18nFlag = doc.getProperty("i18n"/*AbstractDocument.I18NProperty*/);
if ((i18nFlag != null) && i18nFlag.equals(Boolean.TRUE)) {
    // build a view that support bidi
    return createI18N(elem);
} else {
    JTextComponent c = getComponent();
    if (c instanceof JTextArea) {
    JTextArea area = (JTextArea) c;
    View v;
    if (area.getLineWrap()) {
        v = new WrappedPlainView(elem, area.getWrapStyleWord());
    } else {
        v = new PlainView(elem);
    }
    return v;
    }
}
return null;
}

彼が私に何をするように言っているかについての一般的な考えは理解していますが、それを行う方法がわかりません。また、デフォルトのJTextAreaの「プロパティ」を上書きしたくないので、デフォルトを使用するか、カスタムを使用するかを選択できます。

JTextAreaコードの変更のみが

y += fontHeight

y+= (fontHeight +(or -) additionalSpacing)

どうすればこれを達成できますか?どのクラスを使用/コピーしますか?どこに置けばいいの?それらを使用可能にするにはどうすればよいですか?どうすればすべてを機能させることができますか?

これがあまりにも具体的すぎて役に立たないと思う場合は、既存のコンポーネントに100%基づいてカスタムスイングコンポーネントを作成する方法に関する一般的なチュートリアルを誰かが書くことができます。次に、誰かがいくつかの値を簡単に変更して、ニーズに合わせて調整することができます。

4

2 に答える 2

10

私は単にあなたの他の質問から私の答えをコピーして貼り付けるつもりです。

JTextAreaの行の間隔を変更したい

私が最初に考えたのは、オーバーライドjavax.swing.JTextArea#getRowHeightで十分だということでした。javadocは明確に述べています

行の高さの意味を定義します。これはデフォルトでフォントの高さになります。

したがって、このメソッドをオーバーライドすることで、定義を調整し、行間の間隔を広げることを期待していました。バマー、動作しませんでした。JDKでのそのメソッドの使用法をすばやく検索すると、同じことがわかりました。これは主にいくつかのサイズを計算するために使用されますが、コンポーネント内のテキストをペイントする場合は確かに使用されません。

javax.swing.text.PlainView#paintメソッドのソースコードを見ると、FontMetricsが使用されており、で簡単にオーバーライドできることがわかりましたJTextArea。したがって、2番目のアプローチは、拡張することでしたJTextArea(bwah、Swingコンポーネントを拡張しますが、概念実証用です)

  private static class JTextAreaWithExtendedRowHeight extends JTextArea{
    private JTextAreaWithExtendedRowHeight( int rows, int columns ) {
      super( rows, columns );
    }

    @Override
    public FontMetrics getFontMetrics( Font font ) {
      FontMetrics fontMetrics = super.getFontMetrics( font );
      return new FontMetricsWrapper( font, fontMetrics );
    }
  }

クラスはFontMetricsWrapper基本的に、getHeightメソッドを除くすべてを委任します。その方法では、デリゲートの結果に10を追加しました

@Override
public int getHeight() {
  //use +10 to make the difference obvious
  return delegate.getHeight() + 10;
}

そしてこれはより多くの行間隔をもたらします(そしてカレットは長すぎますが、おそらくそれは調整することができます)。

これを説明するための小さなスクリーンショット(他のいくつかのものほど良くはありませんが、このアプローチが機能する可能性があることを示しています):

通常のテキスト領域と拡張テキスト領域の違い

小さな免責事項:これは醜いハックのように感じられ、予期しない問題が発生する可能性があります。誰かがより良い解決策を持って来ることを願っています。

私は個人的にStanislavLが提案している解決策を好みますが、これはあなたに代替手段を与えます

于 2012-10-26T06:15:27.043 に答える
6

これはコードの一部です。まだ終わっていません。折り返し行間の行間隔は実装されていません。WrappedPlainViewまたはの完全なソースを取得PlainViewし、そこにコードを追加して、目的の行間隔を実現できます

import javax.swing.*;
import javax.swing.plaf.basic.BasicTextAreaUI;
import javax.swing.text.*;

public class LineSpacingTextArea {

    public static void main(String[] args) {
        JTextArea ta=new JTextArea();
        JFrame fr=new JFrame("Custom line spacing in JTextArea");
        fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        ta.setText("Line 1\nLine 2\nLong text to show how line spacing works");
        ta.setLineWrap(true);
        ta.setWrapStyleWord(true);
        ta.setUI(new CustomTextAreaUI());
        fr.add(new JScrollPane(ta));
        fr.setSize(100,200);
        fr.setLocationRelativeTo(null);

        fr.setVisible(true);
    }

    static class CustomTextAreaUI extends BasicTextAreaUI {

        public View create(Element elem) {
            Document doc = elem.getDocument();
            Object i18nFlag = doc.getProperty("i18n"/*AbstractDocument.I18NProperty*/);
            if ((i18nFlag != null) && i18nFlag.equals(Boolean.TRUE)) {
                // build a view that support bidi
                return super.create(elem);
            } else {
                JTextComponent c = getComponent();
                if (c instanceof JTextArea) {
                    JTextArea area = (JTextArea) c;
                    View v;
                    if (area.getLineWrap()) {
                        v = new CustomWrappedPlainView(elem, area.getWrapStyleWord());
                    } else {
                        v = new PlainView(elem);
                    }
                    return v;
                }
            }
            return null;
        }
    }

    static class CustomWrappedPlainView extends WrappedPlainView {
        public CustomWrappedPlainView(Element elem, boolean wordWrap) {
            super(elem, wordWrap);
        }
        protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets, int[] spans) {
            super.layoutMajorAxis(targetSpan, axis, offsets, spans);
            int ls=spans[0];
            for (int i=0; i<offsets.length; i++) {
                offsets[i]+=i*ls;
            }
        }
    }
}
于 2012-10-25T06:50:26.210 に答える