JPopupMenu

Discussion in 'Java' started by Richard A. DeVenezia, Jan 14, 2004.

  1. How do I respond to menu selections ?

    I have FigurePanel, which is a subclass of JPanel. The constructor calls
    init() which is

    public class FigurePanel extends javax.swing.JPanel implements
    java.io.Serializable, MouseListener, MouseMotionListener {
    /*stuff*/

    JPopupMenu cutMenu;

    void init (double llx, double lly, double urx, double ury) {
    /*stuff*/
    cutMenu = new JPopupMenu();
    cutMenu.add(new JMenuItem("Cut"));
    cutMenu.add(new JMenuItem("Cancel"));
    }

    public void mouseClicked(MouseEvent e) {
    /*stuff*/
    cutMenu.show(e.getComponent(),e.getX(),e.getY());
    /*stuff*/
    }

    The menu appears and I can select Cut or Cancel or click somewhere off the
    menu and the menu goes away.

    I don't know how to have my panel respond to
    Cut selected
    Cancel selected
    Menu lost focus (do same thing as Cancel)
    .....

    I tried
    cutMenu.add(new JMenuItem("Cut")).addActionListener(thsi);
    but the compiler barked
    addActionListener(java.awt.event.ActionListener) in
    javax.swing.AbstractButton cannot be applied to (FigurePanel)


    I would love to be able to simply do
    JMenuItem selected = cutMenu.show(e.getComponent(),e.getX(),e.getY());
    but that is not in the cards.

    Thanks
    --
    Richard A. DeVenezia
    Richard A. DeVenezia, Jan 14, 2004
    #1
    1. Advertising

  2. Richard A. DeVenezia

    Carl Guest

    Richard A. DeVenezia wrote:

    > How do I respond to menu selections ?
    >
    > I have FigurePanel, which is a subclass of JPanel. The constructor calls
    > init() which is
    >
    > public class FigurePanel extends javax.swing.JPanel implements
    > java.io.Serializable, MouseListener, MouseMotionListener {
    > /*stuff*/
    >
    > JPopupMenu cutMenu;
    >
    > void init (double llx, double lly, double urx, double ury) {
    > /*stuff*/
    > cutMenu = new JPopupMenu();
    > cutMenu.add(new JMenuItem("Cut"));
    > cutMenu.add(new JMenuItem("Cancel"));
    > }
    >
    > public void mouseClicked(MouseEvent e) {
    > /*stuff*/
    > cutMenu.show(e.getComponent(),e.getX(),e.getY());
    > /*stuff*/
    > }
    >
    > The menu appears and I can select Cut or Cancel or click somewhere off the
    > menu and the menu goes away.
    >
    > I don't know how to have my panel respond to
    > Cut selected
    > Cancel selected
    > Menu lost focus (do same thing as Cancel)
    > ....
    >
    > I tried
    > cutMenu.add(new JMenuItem("Cut")).addActionListener(thsi);
    > but the compiler barked
    > addActionListener(java.awt.event.ActionListener) in
    > javax.swing.AbstractButton cannot be applied to (FigurePanel)
    >
    >
    > I would love to be able to simply do
    > JMenuItem selected = cutMenu.show(e.getComponent(),e.getX(),e.getY());
    > but that is not in the cards.
    >
    > Thanks


    FigurePanel should implement ActionListener before registering it as an
    ActionListener. You must also include the ActionPerformed(ActionEvent e)
    method. Query the ActionEvent object for the button that was pressed.

    HTH.
    Carl, Jan 14, 2004
    #2
    1. Advertising

  3. Richard A. DeVenezia

    Chris Smith Guest

    Hi Richard,

    Richard A. DeVenezia wrote:
    > How do I respond to menu selections ?
    >


    You add an ActionListener to the menu item.

    > I tried
    > cutMenu.add(new JMenuItem("Cut")).addActionListener(thsi);
    > but the compiler barked
    > addActionListener(java.awt.event.ActionListener) in
    > javax.swing.AbstractButton cannot be applied to (FigurePanel)


    There are a couple problems there:

    First, you are adding the ActionListener to the wrong thing. Rather
    than adding the listener to the entire popup menu, you want to add it to
    a specific menu item. Thus,

    JMenuItem cutItem = new JMenuItem("Cut");
    JMenuItem cancelItem = new JMenuItem("Cancel");

    cutMenu.add(cutItem);
    cutMenu.add(cancelItem);

    cutItem.addActionListener(...);
    cancelItem.addActionListener(...);

    Second, the thing you're adding needs to actually *be* an
    ActionListener. The easiest way to do this for very trivial cases is to
    use an anonymous inner class, so the last two lines of code above
    become:

    cutItem.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e)
    {
    ...
    }
    });

    cancelItem.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e)
    {
    ...
    }
    });

    If the code in those anonymous classes gets larger, though, you'll want
    to move them to named classes, and end up with:

    cutItem.addActionListener(new CutActionHandler());
    cancelItem.addActionListener(new CancelActionHandler());

    For mid-range cases where you don't want to use an anonymous class, but
    don't want to create a named class either, you can have an anonymous
    inner class delegate to a method in the outer class. I find this to be
    a decent compromise in many situations, and do it quite a bit:

    cutItem.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e)
    {
    cut();
    }
    });

    cancelItem.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e)
    {
    cancel();
    }
    });

    then later,

    private void cut()
    {
    ...
    }

    private void cancel()
    {
    ...
    }

    > I don't know how to have my panel respond to
    > Cut selected
    > Cancel selected
    > Menu lost focus (do same thing as Cancel)


    The method-delegation above is particularly nice here because you've
    expressed a desire to re-use the cancel code in another context from the
    same outer class. So you could also do this:

    cutMenu.addPopupMenuListener(new PopupMenuListener() {
    public void popupMenuCanceled(PopupMenuEvent e)
    {
    cancel();
    }

    ...
    });

    (At the ellipse, you'll need to also implement the other listener
    methods from PopupMenuListener, because there quite inexplicably seems
    to be no PopupMenuAdapter class in Swing.)

    > I would love to be able to simply do
    > JMenuItem selected = cutMenu.show(e.getComponent(),e.getX(),e.getY());
    > but that is not in the cards.


    No, it's not. GUI development is done in an event-driven environment.

    --
    www.designacourse.com
    The Easiest Way to Train Anyone... Anywhere.

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
    Chris Smith, Jan 14, 2004
    #3
  4. Richard A. DeVenezia

    Chris Smith Guest

    Carl wrote:
    > FigurePanel should implement ActionListener before registering it as an
    > ActionListener. You must also include the ActionPerformed(ActionEvent e)
    > method. Query the ActionEvent object for the button that was pressed.


    That's one way to do it. It's generally considered a bad idea, though.
    Even if you do it that way, it needs actionPerformed(ActionEvent), not
    ActionPerformed(ActionEvent).

    The better direction is to move FigurePanel away from implementing any
    listener interfaces at all. Having a class implement a listener
    interface constitutes an invitation to add it as a listener to arbitrary
    other components; when that's not a sensible thing to do, the interface
    in that class's API is misleading.

    --
    www.designacourse.com
    The Easiest Way to Train Anyone... Anywhere.

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
    Chris Smith, Jan 14, 2004
    #4
  5. Richard A. DeVenezia

    Carl Guest

    Chris Smith wrote:

    > Carl wrote:
    >> FigurePanel should implement ActionListener before registering it as an
    >> ActionListener. You must also include the ActionPerformed(ActionEvent e)
    >> method. Query the ActionEvent object for the button that was pressed.

    >
    > That's one way to do it. It's generally considered a bad idea, though.
    > Even if you do it that way, it needs actionPerformed(ActionEvent), not
    > ActionPerformed(ActionEvent).
    >


    Point well taken on the typo.
    Your example is clearly a better solution in the end, I was simply trying to
    make an example that would easily 'blend' the code provided (already
    implementing interfaces, etc.), which the original poster seems to already
    have an understanding of.

    > The better direction is to move FigurePanel away from implementing any
    > listener interfaces at all. Having a class implement a listener
    > interface constitutes an invitation to add it as a listener to arbitrary
    > other components; when that's not a sensible thing to do, the interface
    > in that class's API is misleading.
    >


    Although I agree with what I *think* your argument in this statement, I
    can't say I fully understand it. I certainly don't believe that this
    example "constitutes" any relationship with any "arbitrary" component ;^) .
    Even if the interface is implemented, it's still a 'FigurePanel', and never
    claims to be an "arbitraryComponentListener", at least not any more than
    the javax.swing.JComboBox does, right?

    Cheers,
    Carl.
    Carl, Jan 14, 2004
    #5
  6. Richard A. DeVenezia

    Chris Smith Guest

    Carl wrote:
    > > The better direction is to move FigurePanel away from implementing any
    > > listener interfaces at all. Having a class implement a listener
    > > interface constitutes an invitation to add it as a listener to arbitrary
    > > other components; when that's not a sensible thing to do, the interface
    > > in that class's API is misleading.

    >
    > Although I agree with what I *think* your argument in this statement, I
    > can't say I fully understand it. I certainly don't believe that this
    > example "constitutes" any relationship with any "arbitrary" component ;^) .


    Okay, so arbitrary was the wrong word. Clearly, any class will have a
    specific purpose that's described in its documentation, and can't be
    applied arbitrarily. However, I do think that implementing the listener
    interface (which *is* a part of the classes public API) constitutes an
    implication that the class is intended to be registered as a listener by
    *external* code... something that is misleading in this context.

    > Even if the interface is implemented, it's still a 'FigurePanel', and never
    > claims to be an "arbitraryComponentListener", at least not any more than
    > the javax.swing.JComboBox does, right?


    I'll agree with the part about "any more than JComboBox does".
    JComboBox is an example of this kind of sloppy treatment of public API,
    made even worse by its being not only public, but published and very
    widely distributed. In other words, I think JComboBox is an example of
    a poor programming technique.

    --
    www.designacourse.com
    The Easiest Way to Train Anyone... Anywhere.

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
    Chris Smith, Jan 14, 2004
    #6
  7. "Richard A. DeVenezia" <> wrote in message
    news:bu3s84$d24s3$-berlin.de...
    | How do I respond to menu selections ?
    |
    | I have FigurePanel, which is a subclass of JPanel. The
    constructor calls
    | init() which is

    Why do you use init() as the name of a
    method in a panel? It is too easy to
    confuse with applets.

    | public class FigurePanel extends javax.swing.JPanel implements
    | java.io.Serializable, MouseListener, MouseMotionListener {
    | /*stuff*/

    Please do not supply 'snippets'. That 'stuff'
    you cut may or may not be the important bit,
    I suggest you prepare an example.
    http://www.physci.org/codes/sscce.jsp

    --
    Andrew Thompson
    * http://www.PhySci.org/ PhySci software suite
    * http://www.1point1C.org/ 1.1C - Superluminal!
    * http://www.AThompson.info/andrew/ personal site
    Andrew Thompson, Jan 14, 2004
    #7
  8. "Chris Smith" <> wrote in message
    news:4.net...
    > Hi Richard,
    >

    snippety
    >
    > For mid-range cases where you don't want to use an anonymous class, but
    > don't want to create a named class either, you can have an anonymous
    > inner class delegate to a method in the outer class. I find this to be
    > a decent compromise in many situations, and do it quite a bit:
    >


    Thanks for the help. I totally spaced needing ActionListener.
    I took your advice and went for the 'intermediate' form (method-delegation)
    that uses an inner
    class to dispatch the response to the event.

    > > cutMenu.add(new JMenuItem("Cut")).addActionListener(this);


    > First, you are adding the ActionListener to the wrong thing. Rather
    > than adding the listener to the entire popup menu, you want to add it to
    > a specific menu item.


    JMenuItem.add() returns a JMenuItem, so I can suffix with
    ..addActionListener(<whatever>).

    cutMenu.add(new JMenuItem("Cut"))
    .addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent e){ cut(); }
    });

    --
    Richard A. DeVenezia
    Richard A. DeVenezia, Jan 15, 2004
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. thierry
    Replies:
    0
    Views:
    412
    thierry
    Oct 16, 2003
  2. Sam Brightman
    Replies:
    18
    Views:
    3,848
    Andrew Thompson
    Dec 10, 2003
  3. Harald Hein

    JPopupMenu Flicker/Disappear

    Harald Hein, Dec 6, 2003, in forum: Java
    Replies:
    2
    Views:
    740
    Sam Brightman
    Dec 8, 2003
  4. Vincent Cantin
    Replies:
    3
    Views:
    1,563
    Vincent Cantin
    Aug 6, 2004
  5. Will Barker

    Notification of JPopupMenu dismissal

    Will Barker, Nov 23, 2004, in forum: Java
    Replies:
    2
    Views:
    562
    Babu Kalakrishnan
    Nov 23, 2004
Loading...

Share This Page