2010-11-09 3 views
1

Je semble avoir un problème avec JTextPane. J'ai étendu JTextPane pour rendre une image flottante parce que la fonctionnalité de l'icône JTextPane ne correspond pas à mon objectif. Je souhaite que l'utilisateur puisse cliquer sur l'image et que certains événements soient exécutés. Cependant, lorsque je clique sur l'image, même lorsque j'utilise evt.consume(), le curseur et la sélection sont mis à jour dans le JTextPane. Je souhaite généralement que les clics et les événements de la souris interagissent avec l'image pour ne pas affecter la position du curseur ou la sélection. Code pertinent:À l'aide d'un JTextPane, les événements de souris consommés continuent de se propager aux mises à jour/mises à jour de mise en garde/insertion

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

J'ai même appelé getMouseListeners et vérifié que mon écouteur de souris est le dernier dans le tableau, je lis que les auditeurs sont appelés du plus haut au plus bas indice, ce qui signifie que mes appels d'auditeurs consomment, il devrait être le dernier à agir sur l'événement. Pourquoi est-ce que mon événement de clic de souris met toujours à jour le curseur alors? Est-ce un problème avec le Look and Feel?

+0

Je pense que je peux avoir trouvé un indice, le caret pour JTextPane est par défaut le BasicCaret de BasicTextUI, qui est essentiellement une copie exacte de DefaultCaret. La méthode de mise à jour DefaultCaret est la suivante: protected void moveCaret (MouseEvent e) { \t Point pt = nouveau Point (e.getX(), e.getY()); \t Position.Bias [] biasRet = nouvelle position.Bias [1]; \t int pos = composant.getUI(). ViewToModel (composant, pt, biasRet); \t if (biasRet [0] == nul) \t biasRet [0] = Position.Bias.Forward; \t si (pos> = 0) { \t moveDot (pos, biasRet [0]); \t} } Notez le manque de if (! E.isConsumed) –

Répondre

1

Je lis que les auditeurs sont appelés du plus haut au plus bas indice, ce qui signifie si consomment mes appels d'écoute, il devrait être le dernier à agir sur l'événement

Cette commande est pas garantie. Tout ce qui est garanti, c'est que tous les auditeurs seront avertis. Je crois que c'est à chaque auditeur de vérifier si l'événement est consommé. Au moins c'est ma compréhension

Vous pourriez être en mesure d'utiliser un Global Event Dispatcher pour empêcher l'événement d'être distribué au composant. Rappelez-vous simplement que tous les événements passent par le répartiteur de sorte que le code doit être efficace afin de ne pas ralentir la file d'attente.

Ou vous pouvez utiliser la technique présentée sur Mouse Wheel Controller qui supprime tous les écouteurs des composants et les remplace avec votre écouteur personnalisé. Vous pouvez ensuite décider quand transférer les événements à l'autre écouteur.

Ou peut-être votre image devrait être peinte sur la fenêtre, pas sur le volet de texte.

+0

Alors que ma réponse ci-dessus a créé le comportement que je désirais, il est clair que vous êtes plus familier avec les meilleures pratiques que moi en disant que l'image doit être peinte dans la fenêtre et non dans le volet texte. Je vais explorer cette solution aussi. –

0

Résolu en créant mon propre curseur. Le problème était que l'implémentation DefaultCaret ne vérifiait PAS e.isConsumed sur les événements de souris, vous devez donc remplacer et ajouter la vérification isconsumed. Mon textPane se comporte comme prévu maintenant que j'ai le code suivant dans le constructeur:

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

Ce fut ma faute pour ne pas comprendre pleinement le rôle du Caret dans le modèle d'événement. Mais, si vous me demandez c'est un peu idiot. D'après la documentation que j'ai lue, la convention veut que tous les auditeurs agissent uniquement de façon tangible si! E.isConsumed().

Questions connexes