2

Swing に問題があり、その理由がわかりません。背景画像を表示するために拡張された JTextPane があります。これは、ラスター イメージ (標準 Java API を介して表示) または SVG ベクター イメージ (SVG Salamander を介して表示) のいずれかです。

テキスト ペインの上部に、テキストを表示しない余白として使用する領域を設定したいので、次のようにします。テキストなどが表示され、最後に背景画像の一部を再びペイントしますが、クリッピング四角形を使用して、上部の余白領域にあるテキストのみをカバーします。

これは、私が何日も戦ってきた小さな問題を除けば、まったく問題なく機能します。ラスター イメージでは、テキスト ペインでテキストを選択すると、テキストが強調表示されるのではなく削除されます。つまり、テキストを選択すると、選択している部分の上に背景画像が表示されます。画像を描画する最初の呼び出しは super.paintComponent() の前に呼び出され、2 番目の呼び出しにはクリッピング四角形があるため、余白のみを描画し、そうしなければすべて正常に動作するため、これが可能である理由がわかりません。選択しないでください。いくつかの追加の手がかり:

  • コメントしてもこの問題は発生しないので、2 番目の呼び出しに関連するものであることはわかっています (ただし、マージンはありません)。
  • 不思議なことに、背景がベクター画像の場合は発生せず、ラスター画像のみです。

私の paintComponent() メソッドのコードは次のとおりです。

public void paintComponent(Graphics g)
{
    Rectangle rect = null;
    if ( rasterBackgroundImage != null )
    {
        rect = getVisibleRect();
        g.drawImage(rasterBackgroundImage.getImage(),rect.x,rect.y,rect.width,rect.height,this);
    }
    if ( vectorBackgroundImage != null )
    {
        rect = getVisibleRect();
        vectorBackgroundImage.setPreferredSize(new Dimension(rect.width,rect.height));
        vectorBackgroundImage.setScaleToFit(true);
        vectorBackgroundImage.paintIcon(this, g, rect.x, rect.y);
    }

    super.paintComponent(g);

    //if we want a non-scrolling top margin
    if ( rasterBackgroundImage != null )
    {
        g.setClip(rect.x,rect.y,rect.width,getMargin().top);
        g.drawImage(rasterBackgroundImage.getImage(),rect.x,rect.y,rect.width,rect.height,this);
    }
    if ( vectorBackgroundImage != null )
    {
        g.setClip(rect.x,rect.y,rect.width,getMargin().top);
        vectorBackgroundImage.setPreferredSize(new Dimension(rect.width,rect.height));
        vectorBackgroundImage.paintIcon(this, g, rect.x, rect.y);
    }

}

クラス全体を見たい人は、ここにあります: http://code.google.com/p/aetheria/source/browse/trunk/age/src/eu/irreality/age/swing/FancyJTextPane .java?r=301

問題は他のクラスとの相互作用にあると思われるため、修正を求めているわけではないことに注意してください。そのため、私は SSCCE を提供しませんでした: SSCCE を作成しようとしましたが、このクラスを単独で使用すると... 実際には機能します。システム全体の外で問題を再現できず、どの相互作用が問題を引き起こすのかわかりません。しかし、私を正しい方向に向けるヒントを提供してくれる人には非常に感謝しています-おそらく誰かがこの種のことを以前に見たことがあり、何原因であるかの手がかりを持っている可能性があります...

更新: setClip() の使用をやめることで、問題を回避できました。PaintComponent() で setClip() を使用しないことを推奨するこの回答を見つけました: Java スイング クリッピングの問題

クリッピング四角形を使用する代わりに、余白に描画したい画像の上部を含むサブ画像を作成し、setClip() を呼び出さずに直接描画します。1つで十分なはずのメモリに2つの画像を保存しているため、おそらく非常に非効率的ですが、少なくとも動作します(tm)。このハックに興味がある人は、こちらをご覧ください (現時点ではコードが少し汚れています): http://code.google.com/p/aetheria/source/browse/trunk/age/src/eu/irreality /age/swing/FancyJTextPane.java?r=305

それでも、 setClip() をこのように使用するとこれらの問題が発生する正確な原因を特定できる人、またはこれを解決する効率的な方法を知っている人がいれば、興味深いでしょう。すべての答えをありがとう!:)

4

2 に答える 2

3

@mKorbelの役立つリンクに加えて、ここにいくつかのアイデアがあります。

  • BorderLayout親コンテナのレイアウトを確認し、 forJFrameFlowLayoutforなどのインセットとデフォルトに注意してくださいJPanel。あなたが観察したように、対照的な色が役立つことがあります。

  • Windowでは、「これにより、サブコンポーネントの優先サイズとレイアウトに合うサイズになるpack()」ため、少なくとも1回は呼び出す必要があります。Window

  • の使用法を批判的に検討し、他の場合ではなく、同様setPreferredSize()に必要になる可能性があることに注意してください。revalidate()repaint()

  • エディタペインとテキストペインの使用方法の例を確認してください。

  • 余談ですが、ド・モルガンの法則set*BackgroundImage()がメソッドの述語を単純化できるかどうかを検討してください。

    setOpaque(!(rasterBackgroundImage == null && vectorBackgroundImage == null));
    
于 2011-06-18T19:33:51.863 に答える
3

JLabelHow To Use Icon存在する場合、paintComponent(s) を使用してイメージをペイントする必要があるのはなぜですか?

于 2011-06-18T11:42:53.613 に答える