Link to home
Start Free TrialLog in
Avatar of castello
castello

asked on

mouse event handling code doesn't work

Why doesn't this code work, and what do I need to do to fix it?
What I want to happen is when the user right clicks, the popup menu should come up.  When the user left clicks, plyKey() should be called.  What's happening is when the user right clicks, the menu comes up, but plyKey() also executes.  And the method executes with a left click also.

public class PblKbd
   extends Canvas
   implements ActionListener
{  
...

   public PblKbd(...,...,...,...)
   {
      ...

         // Listen for mouse clicks.
         this.addMouseListener(new MouseAdapter(){});

         public void processMouseEvent(MouseEvent me)
         {
             int x = me.getX();
             int y = me.getY();
       
       
             if (true == me.isPopupTrigger())
             {
                 popMnu.show(this,x,y);
              }
              if (false == me.isPopupTrigger())
              {
                  plyKey(x,y);
               }
               me.consume();
         }

      ...

     }
...
}
Avatar of Jan Louwerens
Jan Louwerens
Flag of United States of America image

your problem is in the following line:

 this.addMouseListener(new MouseAdapter(){});

The MouseAdapter class is only a convenience class the implements all the methods in the MouseListener interface. However, all these methods do nothing by default. It is meant to be extended by a user class that only wants to implement one or a small number of methods defined by the MouseListener interface.
In your case, you will want to define your class like:

public class PblKbd extende Canvas implements MouseListener
{
....
(implement all methods of the MouseLintener interface within your class)
}
Avatar of castello
castello

ASKER

Now, I get no response from a left or right click.  Nothing happens.

I changed
implements ActionListener
to
implements ActionListener, MouseListener

and I got rid of

this.addMouseListener(new MouseAdapter(){});
and the processMouseEvent() method

and added

public void mousePressed(MouseEvent e)
    {
       int x = e.getX();
       int y = e.getY();
       
       
       if (true == e.isPopupTrigger())
       {
          popMnu.show(this,x,y);
       }
       if (false == e.isPopupTrigger())
       {
          plyKey(x,y);
       }
       e.consume();  
    }
    public void mouseClicked(MouseEvent e)
    {
    }
    public void mouseEntered(MouseEvent e)
    {
    }
    public void mouseExited(MouseEvent e)
    {
    }
    public void mouseReleased(MouseEvent e)
    {
    }
Now, I get no response from a left or right click.  Nothing happens.

I changed
implements ActionListener
to
implements ActionListener, MouseListener

and I got rid of

this.addMouseListener(new MouseAdapter(){});
and the processMouseEvent() method

and added

public void mousePressed(MouseEvent e)
    {
       int x = e.getX();
       int y = e.getY();
       
       
       if (true == e.isPopupTrigger())
       {
          popMnu.show(this,x,y);
       }
       if (false == e.isPopupTrigger())
       {
          plyKey(x,y);
       }
       e.consume();  
    }
    public void mouseClicked(MouseEvent e)
    {
    }
    public void mouseEntered(MouseEvent e)
    {
    }
    public void mouseExited(MouseEvent e)
    {
    }
    public void mouseReleased(MouseEvent e)
    {
    }
Try first to print to console the coordinates of the mouse, to see if you pass by there.
add this after you read the coordinates :

System.out.println("x : "+x+"\ny : "+y);
7.5 Scribbling with Inner Classes
The Java 1.1 event model was designed to work well with another new Java 1.1 feature: inner classes. Example 7.3 shows what the applet looks like when the event listeners are implemented as anonymous inner classes. Note how succinct this representation is. This is perhaps the most common way to use the Java 1.1 event model, so you'll probably see a lot of code that looks like this. In this case, our simple applet is nothing but event-handling code, so this version of it consists almost entirely of anonymous class definitions.

Note that we've added a feature to the applet. It now includes a Clear button. An ActionListener object is registered with the button; it clears the scribble when the appropriate event occurs.

Example 7.3: Scribble: Using Inner Classes

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class Scribble3 extends Applet {
  int last_x, last_y;
  public void init() {
    // Define, instantiate, and register a MouseListener object.
    this.addMouseListener(new MouseAdapter() {
      public void mousePressed(MouseEvent e) {
        last_x = e.getX();
        last_y = e.getY();
      }
    });
    // Define, instantiate, and register a MouseMotionListener object.
    this.addMouseMotionListener(new MouseMotionAdapter() {
      public void mouseDragged(MouseEvent e) {
        Graphics g = getGraphics();
        int x = e.getX(), y = e.getY();
        g.setColor(Color.black);
        g.drawLine(last_x, last_y, x, y);
        last_x = x; last_y = y;
      }
    });
    // Create a clear button.
    Button b = new Button("Clear");
    // Define, instantiate, and register a listener to handle button presses.
    b.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {  // clear the scribble
        Graphics g = getGraphics();
        g.setColor(getBackground());
        g.fillRect(0, 0, getSize().width, getSize().height);
      }
    });
    // And add the button to the applet.
    this.add(b);
  }
}

Ovi, I know that I get the right coordinates of the mouse.  I didn't mention (or post the code) but I have some debugging code in the applet that displays x and y.  Actually, for now, this particular code is taking the place of plyKey(), so when plyKey is called, x,y is displayed instead.  I did this because I wanted to debug from my appletviewer at home and not keep going to my web account online - plyKey() plays .au files.

vladi21, your suggestion is what I started with.  But it's not working because I'm using the show() method for the popup, which takes the component to display in as an argument.  When I use
popMnu.show(this,e.getX(),e.getY());
I get a compile error
Incompatible type for method.  Can't convert PblKbd.1 to java.awt.Component.
because 'this' refers to the annonymous inner class MouseListener. I was trying to figure out how to refer to the PblKbd as the component to display the popup in, and that's what led me to my original post. I was using a method outside the constructor so that I would have access to PblKbd via 'this'. (I see now that when I typed my original post I mistakenly put the processing method in the constructor.)

How to 1) refer to PblKbd in show() in an AIC, or 2) do the mouse listening using the interface and a method outside the constructor is what I need.

Here's the code that generated the error:

this.addMouseListener(new MouseAdapter(){
         public void mousePressed(MouseEvent e){
            int x = e.getX();
            int y = e.getY();
            if (true == e.isPopupTrigger())
            {
               popMnu.show(this,x,y);          
            }
            else
            {
               plyKey(x,y);
            }
            e.consume();
         }
});
try
popMnu.show(PblKbd.this,x,y);          
           
If I have understood correctly and you want to get a link back out to the outer class that has created your inner class then you need to know how an inner class is connected to it's outer class "container":

********************

Referring to the outer class object

If you need to produce the handle to the outer class object, you name the outer class followed by a dot and this. For example, in the class Sequence.SSelector, any of its methods can produce the stored handle to the outer class Sequence by saying Sequence.this. The resulting handle is automatically the correct type. (This is known and checked at compile time, so there is no run-time overhead.)

Sometimes you want to tell some other object to create an object of one of its inner classes. To do this you must provide a handle to the other outer class object in the new expression, like this:

//: Parcel11.java
// Creating inner classes
package c07.parcel11;

public class Parcel11 {
  class Contents {
    private int i = 11;
    public int value() { return i; }
  }
  class Destination {
    private String label;
    Destination(String whereTo) {
      label = whereTo;
    }
    String readLabel() { return label; }
  }
  public static void main(String[] args) {
    Parcel11 p = new Parcel11();
    // Must use instance of outer class
    // to create an instances of the inner class:
    Parcel11.Contents c = p.new Contents();
    Parcel11.Destination d =
      p.new Destination("Tanzania");
  }
} ///:~

To create an object of the inner class directly, you don’t follow the same form and refer to the outer class name Parcel11 as you might expect, but instead you must use an object of the outer class to make an object of the inner class:

Parcel11.Contents c = p.new Contents();


Thus, it’s not possible to create an object of the inner class unless you already have an object of the outer class. This is because the object of the inner class is quietly connected to the object of the outer class that it was made from. However, if you make a static inner class, then it doesn’t need a handle to the outer class object.

****************

So in your case, to get your link back to the PblKbd outer class you can do this:

this.addMouseListener(new MouseAdapter(){
         public void mousePressed(MouseEvent e){
            int x = e.getX();
            int y = e.getY();
            if (true == e.isPopupTrigger())
            {
               popMnu.show(PblKbd.this,x,y);          
            }
            else
            {
               plyKey(x,y);
            }
            e.consume();
         }
});


Thus, PblKbd.this gets you the reference to the outer class object that you need for the menu call.

Is this what you need to know?

so u can submit answer
I tried
popMnu.show(PblKbd.this,x,y);
It compiled, but when I right click, plyKey() executes.
When I left click, plyKey() executes.
The menu doesn't come up when I right click.

What seems most odd is that plyKey() executes no matter which key is clicked even though it's part of an 'else'.......
this.addMouseListener(new MouseAdapter(){
         public void mousePressed(MouseEvent e){
            int x = e.getX();
            int y = e.getY();
System.out.println(e.isPopupTrigger());
            if (true == e.isPopupTrigger())
            {
               popMnu.show(PblKbd.this,x,y);            
            }
            else
            {
               plyKey(x,y);
            }
            e.consume();
         }
});

post the result

ur platform/OS ?
ASKER CERTIFIED SOLUTION
Avatar of Jod
Jod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Ok, it says the right button is not the popup trigger, which is wierd, because when I was using slightly different code - posted above - a right click did cause the menu to pop up:


this.addMouseListener(new MouseAdapter(){});

                               public void processMouseEvent(MouseEvent me)
                               {
                                   int x = me.getX();
                                   int y = me.getY();
                             
                             
                                   if (true == me.isPopupTrigger())
                                   {
                                       popMnu.show(this,x,y);
                                    }
                                    if (false == me.isPopupTrigger())
                                    {
                                        plyKey(x,y);
                                     }
                                     me.consume();
                               }

Now I'm wondering how differently the mouse might act with different users on the webpage........

I'm using Windows 98 and the appletviewer from JDK1.1.8
and a Cirque touch pad, if that makes any difference.

So now, how do I figure put what the popup trigger is?
Oh.... wait a minute, I'm awake.
This solves the problem.  Thank you.

 if ( ( e.getModifiers() & InputEvent.BUTTON3_MASK ) ==
                      InputEvent.BUTTON3_MASK) {
                                     popMnu.show(PblKbd.this,x,y);              
                                  } else {
                                     plyKey(x,y);
                                  }

be careful using BUTTON3_MASK

some platforms (like McIntosh) don't have a right button (at least in the general case), so you limit the user base of your app that way
....