In java awt or swing, how can I arrange keyboard input wherever the mouse is?

While working on the help system, I would like each component to offer some help when the mouse over it and "?" key pressed. Similar tooltips, with the exception of more extensive help - essentially a small web browser designed to pop up and display text, images, etc.

What I find is that no matter where the mouse is located, the input always goes to the same KeyListener. Should there be only one active at a time?

For what it's worth, this is an already working version - thanks for the suggestions!

  / **
      * Main class JavaHelp wants to support a help function so that when
      * the user types F1 above a component, it creates a popup explaining
      * the component.
      * The full version is intended to be a big brother to tooltips, invoking
      * an HTML display with clickable links, embedded images, and the like.
      * /


     import javax.swing. *;
     import javax.swing.border.Border;
     import java.awt. *;
     import java.awt.event. *;
     import java.awt.event.ActionEvent;
     import java.awt.event.ActionListener;
     import java.awt.event.KeyEvent;
     import java.awt.event.KeyListener;

     class Respond2Key extends AbstractAction
     {
     Component jrp;

     // Contract consructor
     public Respond2Key (String text)
     {
       super (text);
     }

     // Constructor that makes sure it gets done right
     public Respond2Key (String text, Component jrpIn)
     {
       super (text);
       System.out.println ("creating Respond2Key with component" + jrpIn
                                        .toString
                                         ());
       jrp = jrpIn;
     }

     public void setJrp (Component j) {
         jrp = j;
     }


     // Functionality: what is the response to a key
     public void actionPerformed (ActionEvent e)
     {
       // use MouseInfo to get position, convert to pane coords, lookup component
       Point sloc = MouseInfo.getPointerInfo (). GetLocation ();

       SwingUtilities.convertPointFromScreen (sloc, (Component) jrp);

       Component c = jrp.getComponentAt (sloc);
       System.out.printf ("Mouse at% 5.2f,% 5.2f Component under mouse is% s \ n",
                  sloc.getX (), sloc.getY (), c.toString ());
     }
     }


     // ------------------------------------------------ ---------------- 
     // The main class
     // ------------------------------------------------ ---------------- 
     public class JavaHelp extends JFrame
     {
     // The object constructor
     public JavaHelp ()
     {
         // Start construction
         super ("Help System");
         this.setSize (640, 480);
         Container contents = getContentPane ();
         contents.setLayout (new FlowLayout ());


         JButton b1 = butt ("button1", 64, 48);
         JButton b2 = butt ("button2", 96, 48);
         JButton b3 = butt ("button3", 128, 48);
         JPanel p1 = pane ("hello", 100, 100);
         JPanel p2 = pane ("world", 200, 100);

         contents.add (b1);
         contents.add (p1);
         contents.add (b2);
         contents.add (p2);
         contents.add (b3);

         JRootPane jrp = this.getRootPane ();
         jrp.getInputMap (jrp.WHEN_IN_FOCUSED_WINDOW)
         .put (KeyStroke.getKeyStroke ("F1"), "helpAction");
         jrp.getActionMap (). put ("helpAction",
                     new Respond2Key ("frame", (Component) contents)
                     );
         this.setVisible (true);
         this.requestFocus ();
         this.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

     }

     // Inner classes for instantiating and listening to button, and panel.
     class ButtonListener implements ActionListener
     {
       private String label = null;

       public void setLabel (String s) {label = s;}

       public void actionPerformed (ActionEvent e)
       {
         System.out.printf ("Dealing with event labeled% s source% s \ n \ n",
                    label
                    e.getSource (). toString ());
       }

     }

     // def butt (from, name, w, h) = new Jbutton (...)
     protected JButton butt (String s, int w, int h)
     {
       JButton b = new JButton (s);
       b.setSize (w, h);
       ButtonListener oj = new ButtonListener ();
       oj.setLabel (s);
       b.addActionListener (oj);
       return (b);
     }

     // def pane = new Jpanel (...)
     protected JPanel pane (String name, int w, int h)
     {
       JPanel p = new JPanel ();
       p.setMinimumSize (new Dimension (w, h));
       p.add (new Label (name));
       p.setBackground (Color.black);
       p.setForeground (Color.red);
       return (p);
     }

     // --------------------------------
     public static void main (String [] args)
     {
       JavaHelp jh = new JavaHelp ();
     }



     }





+6
source share
2 answers

input always goes to the same KeyListener.

KeyEvent is always sent to the component with focus; the location of the mouse has nothing to do with how the key event is generated.

Instead of using KeyListener you should use Key Bindings . When you use key bindings, you can trigger an action whenever a KeyStroke is generated, adding a binding to the JFrame root panel. For more information, see the Swing Key Bindings tutorial.

Now in the action you create to listen to "?" KeyStroke you can:

  • use the MouseInfo class to get the current location of the mouse.
  • use SwingUtilities.convertPointFromScreen(...) to convert the mouse point to the root panel
  • then you can use Conatiner.getComponentAt(...) to get the actual component the mouse is over.
  • after you learn about the component, you can display your help information.
+3
source

I am sure there is a better way, but one quick and dirty solution:

 private final class HoverFocusListener extends MouseInputAdapter { public void mouseEntered(MouseEvent e) { e.getComponent().requestFocusInWindow(); } } 

Or, if necessary:

 public void mouseEntered(MouseEvent e) { e.getSource().setFocusable(true); for (Component c : refToParent.getComponents()) c.setFocusable(false); e.getComponent().requestFocusInWindow(); } 

Then just .addMouseListener(new HoverFocusListener()) for all the affected components.

+3
source

Source: https://habr.com/ru/post/970509/


All Articles