1

JTextPane に問題があるようです。JTextPane のアイコン機能が目的に合わないため、JTextPane を拡張して浮動イメージをレンダリングしました。ユーザーが画像をクリックして、特定のイベントを実行できるようにしたい。ただし、画像をクリックすると、evt.consume() を使用しても、キャレットと選択が JTextPane で更新されます。画像と相互作用する一般的なクリックとマウスイベントが、キャレットの位置や選択にまったく影響を与えないようにしたいと思います。関連コード:

public class JTextPaneImg extends JTextPane {

    public JTextPaneImg(){
        super();
        addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                formMousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                formMouseReleased(evt);
            }
        });
    }

    private void formMousePressed(java.awt.event.MouseEvent evt) {                                  
        if (imgBound.contains(evt.getPoint())) {
             evt.consume();
             //Do some stuff in here to interact with the image
             // but the event still undesirably interacts with selection/caret
        }
    }   


    private void formMouseReleased(java.awt.event.MouseEvent evt) {                                  
        if (imgBound.contains(evt.getPoint())) {
             evt.consume();
             //Do some stuff in here to interact with the image
             // but the event still undesirably interacts with selection/caret
        }
    }   
}

私は getMouseListeners を呼び出して、自分のマウス リスナーが配列の最後であることを確認しました。リスナーは最大インデックスから最小インデックスの順に呼び出されることを読みました。マウスクリックイベントがまだキャレットを更新しているのはなぜですか? これはルック アンド フィールの問題ですか?

4

2 に答える 2

1

リスナーは最高から最低のインデックスに呼び出されることを読みました。つまり、リスナーの呼び出しが消費される場合、イベントに作用するのは最後でなければなりません

この順序は保証されません。保証されているのは、すべてのリスナーに通知されることだけです。イベントが消費されているかどうかを確認するのは、各リスナー次第だと思います。少なくともそれは私の理解です

Global Event Dispatcherを使用して、イベントがコンポーネントにディスパッチされないようにすることができる場合があります。すべてのイベントがディスパッチャーを通過することを覚えておいてください。コードは効率的であり、キューの速度が低下することはありません。

または、コンポーネントからすべてのリスナーを削除し、それをカスタム リスナーに置き換える、マウス ホイール コントローラーに示されている手法を使用することもできます。次に、イベントを他のリスナーにいつ転送するかを決定できます。

または、テキスト ペインではなく、ビューポートに画像を描画する必要があるかもしれません。

于 2010-11-09T06:26:16.253 に答える
0

独自のキャレットを作成することで解決しました。問題は、DefaultCaret 実装がマウス イベントで e.isConsumed をチェックしないことでした。そのため、isconsumed チェックをオーバーライドして追加する必要があります。コンストラクターに次のコードがあるため、テキストペインは意図したとおりに動作します。

    this.setCaret(new DefaultCaret() {

        @Override
        protected void positionCaret(MouseEvent e) {
            if (!e.isConsumed()) super.positionCaret(e);
        }

        @Override
        protected void moveCaret(MouseEvent e) {
            if (!e.isConsumed()) super.moveCaret(e);
        }
    });

これは、イベント モデルでのキャレットの役割を完全に理解していなかった私のせいです。しかし、あなたが私に尋ねると、これはややばかげています。私が読んだドキュメンテーションから、!e.isConsumed() の場合にのみ、すべてのリスナーが明確に動作するようにするのが慣習です。

于 2010-11-09T06:36:32.660 に答える