Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 316
  • Last Modified:

How to have a global right click menu on all text components in my app?

I need to put a right click menu on all text components in my app.

I want something that will work on the standard swing text components (So no 'extend component and refactor' answers please ) and also on any JDialogs that are created from my app.

Any ideas?
0
riaancornelius
Asked:
riaancornelius
  • 7
  • 5
  • 2
  • +3
2 Solutions
 
CEHJCommented:
What's up with JPopupMenu? ;-)
0
 
riaancorneliusAuthor Commented:
It's to do a copy / paste menu for each text component throughout the app (which is at quarter million lines of code, so I don't want to mess with any existing code if at all possible.)
0
 
CEHJCommented:
Wouldn't it be better to put copy/paste items in the *main* menu anyway?
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
hoomanvCommented:
you cant do it without adding the functionality to TextComponent itself

look at the example here: PopupMenuDemo.java
http://java.sun.com/docs/books/tutorial/uiswing/components/menu.html#popup

you have two options
 1 add mouselistener to each text field individualy
 2 implement your own text component and extend from it
0
 
sciuriwareCommented:
Maybe you like to solve this with a function key? This is a solution for F1:

Add the following code when creating the JFrame:

         Toolkit.getDefaultToolkit().addAWTEventListener(new Ui(), AWTEvent.KEY_EVENT_MASK);

Add the interface to your action class:

                                                  ... implements AWTEventListener

And implement:

   /** (non-Javadoc)
    * @see java.awt.event.AWTEventListener#eventDispatched(java.awt.AWTEvent)
    */
   public void eventDispatched(AWTEvent event)
   {
      if(event instanceof KeyEvent)
      {
         KeyEvent ke = (KeyEvent)event;

         if(ke.getID() == KeyEvent.KEY_PRESSED && ke.getKeyCode() == KeyEvent.VK_F1)  // Choose a function key.
         {
            popMyDialog();           // Here comes whatever action you want.
         }
      }
   }


;JOOP!
0
 
objectsCommented:
try the following EventQueue:

public class PopupEventQueue extends EventQueue
{
    protected void dispatchEvent(AWTEvent event)
    {
        super.dispatchEvent(event);
 
        if (event instanceof MouseEvent)
        {
           MouseEvent me = (MouseEvent)event;
           if (me.isPopupTrigger())
           {
               Component comp = SwingUtilities.getDeepestComponentAt(me.getComponent(),
                                                me.getX(), me.getY());
               if (comp instanceof JTextComponent)
               {
                   if (MenuSelectionManager.defaultManager().getSelectedPath().length==0)
                   {
                       // do popup

                      JTextComponent tc = (JTextComponent)comp;
                      JPopupMenu menu = new JPopupMenu();
                      menu.add(new CutAction(tc));
                      menu.add(new CopyAction(tc));
                      menu.add(new PasteAction(tc));
                      Point p = SwingUtilities.convertPoint(me.getComponent(), me.getPoint(), tc);
                      menu.show(tc, p.x, p.y);
                   }
                }
           }
       }
    }
}
0
 
ksivananthCommented:
the complete example is here,

import javax.swing.text.DefaultEditorKit;
import javax.swing.text.JTextComponent;
import javax.swing.*;
import java.awt.event.AWTEventListener;
import java.awt.event.MouseEvent;
import java.awt.*;

public class TestGlobalRightClick extends JFrame{
    public static final String rightClickAction = "RightClickAction" ;

    private void buildComponents(){
        JPanel pnlMain = new JPanel( new GridBagLayout() ) ;
        JLabel lbl1 = new JLabel( "One" ) ;
        JTextField txt1 = new JTextField( 10 ) ;
        JLabel lbl2 = new JLabel( "Two" ) ;
        JTextField txt2 = new JTextField( 10 ) ;
        JButton btn = new JButton( "Click" ) ;

        pnlMain.add( lbl1, new GridBagConstraints( 0, 0, 1, 1, 0.0, 0.0,
            GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets( 5, 5, 5, 5 ), 0, 0 ) ) ;
        pnlMain.add( txt1, new GridBagConstraints( 1, 0, 1, 1, 0.0, 0.0,
            GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets( 5, 5, 5, 5 ), 0, 0 ) ) ;
        pnlMain.add( lbl2, new GridBagConstraints( 0, 1, 1, 1, 0.0, 0.0,
            GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets( 5, 5, 5, 5 ), 0, 0 ) ) ;
        pnlMain.add( txt2, new GridBagConstraints( 1, 1, 1, 1, 0.0, 0.0,
            GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets( 5, 5, 5, 5 ), 0, 0 ) ) ;

        getContentPane().add( pnlMain, BorderLayout.CENTER ) ;
        getContentPane().add( btn, BorderLayout.SOUTH ) ;

        pack() ;
        setVisible( true ) ;
    }

    public static void main( String arg[] ){
        Toolkit.getDefaultToolkit().addAWTEventListener( new MyAWTListener(), AWTEvent.MOUSE_EVENT_MASK );
        TestGlobalRightClick tgrc = new TestGlobalRightClick() ;
        tgrc.buildComponents();
    }

    public static class MyAWTListener implements AWTEventListener {

        public void eventDispatched( AWTEvent awe ){
            MouseEvent me = ( MouseEvent )awe ;
            if( ! me.isPopupTrigger() ) return ;

            Object source = me.getSource() ;
            if( source instanceof JTextComponent ){
                JTextComponent text = ( JTextComponent )source ;
                JPopupMenu menu = new JPopupMenu();
                menu.add( new DefaultEditorKit.CutAction() );
                menu.add( new DefaultEditorKit.CopyAction() );
                menu.add( new DefaultEditorKit.PasteAction() );
                Point p = SwingUtilities.convertPoint( me.getComponent(), me.getPoint(), text );
                menu.show( text, p.x, p.y );
            }
        }
    }
}
0
 
ksivananthCommented:
you may have to add the focus event mask for hiding the popup when the focus lost for the app.
0
 
riaancorneliusAuthor Commented:
Thanks guys. I'll have a look at your ideas as soon as I get a moment. I was away for the weekend and only got back yesterday, So I'm still a bit swamped.

I think objects solution of extending the eventqueue is most likely to be what I'm looking for.
0
 
ksivananthCommented:
>>I think objects solution of extending the eventqueue is most likely to be what I'm looking for.

just curious, what is the advantage over this?
0
 
riaancorneliusAuthor Commented:
>> just curious, what is the advantage over this?

If you're referring to this:
>> public class TestGlobalRightClick extends JFrame{
>>    public static final String rightClickAction = "RightClickAction" ;
>>    private void buildComponents(){
>> .....

At first glance I think that will only work for the contents of the JFrame, Not for any JDialogs etc...

If I'm wrong, please don't take my head of yet. Like I say, I've only glanced at the solutions.

I will try all the solutions before making a decision on which works better.

:)
0
 
ksivananthCommented:
>>At first glance I think that will only work for the contents of the JFrame, Not for any JDialogs etc...

Nope, it is going to work for all JTextComponent in a swing application regardless of it's container! Ya, you can try all and choose a one that fits you :)

I just wished to know advantageous of other solutions, nothing else ;)
0
 
riaancorneliusAuthor Commented:
No problem. I'll still be busy today, but should have the chance to look at these solutions tonight. I will let you know why I choose whichever solution I do.

Objects: This might be a bit of a dumb question, but what do I do with that PopupEventQueue?
0
 
riaancorneliusAuthor Commented:
Solutions that won't work:

CEHJ: At the moment we hava copy/paste functionality in the main menu. Most users just doesn't look there.
hoomanv: My original question expressly stated that I don't want to mess with individual components. And it can be done :)
sciuriware: Although technically your solution is fine, we have tried it, and it's the same problem. Users just doesn't understand it. (And yes, we do have it very well documented in a pretty easy to use help function. Users apparently can't read either...)

So, I'll look at objects and ksivananth's solutions tonight. They seem like pretty much the same thing though?
0
 
riaancorneliusAuthor Commented:
Never mind objects, found how to push the eventqueue onto the systemEventQueue
0
 
riaancorneliusAuthor Commented:
I've tested both solutions. Both works exactly the way I want, and it still seems like pretty much the same solution to me. So, because objects was first I'll give him most of the points, with a few for ksivananth's effort.

Any objections?
0
 
ksivananthCommented:
No objections!
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 7
  • 5
  • 2
  • +3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now