使用JTextPane,消耗的鼠标事件仍然传播到插入符更新/选择更新

时间:2010-11-09 06:10:24

标签: java events mouseevent jtextpane

我似乎遇到了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并验证我自己的鼠标监听器是数组中的最后一个,我读到从最高到最低的索引调用监听器,这意味着如果我的监听器调用消耗,它应该是最后一个事件。为什么我的鼠标点击事件仍然更新插入符号呢?这是外观的问题吗?

2 个答案:

答案 0 :(得分:1)

  

我读到从最高到最低的索引调用侦听器,这意味着如果我的侦听器调用消耗,它应该是最后一个对事件起作用的

此订单无法保证。所有保证都会通知所有听众。我相信每个听众都应该检查事件是否被消耗。至少这是我的理解

您可以使用Global Event Dispatcher来阻止将事件分派到组件。请记住,所有事件都通过调度程序,因此代码应该是高效的,这样您就不会减慢队列速度。

或者您可以使用Mouse Wheel Controller上提供的技术,该技术会从组件中删除所有侦听器,并将其替换为您的自定义侦听器。然后,您可以决定何时将事件转发给另一个侦听器。

或许您的图像应该在视口上绘制,而不是在文本窗格上绘制。

答案 1 :(得分:0)

通过创建我自己的插入符来解决。问题是DefaultCaret实现不会在鼠标事件上检查e.isConsumed,因此您必须覆盖并添加isconsumed检查。我的textpane就像预期的那样,我在构造函数中有以下代码:

    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);
        }
    });

由于没有完全理解Caret在事件模型中的作用,这是我的错。但是,如果你问我这有点傻。从我读过的文档来看,惯例就是让所有的听众只有在行动时才能切实行动!e.isConsumed()。