在 java awt 或 swing 中,如何安排键盘输入到鼠标所在的位置?

Posted

技术标签:

【中文标题】在 java awt 或 swing 中,如何安排键盘输入到鼠标所在的位置?【英文标题】:in java awt or swing, how can I arrange for keyboard input to go wherever the mouse is? 【发布时间】:2014-07-28 19:57:43 【问题描述】:

在帮助系统上工作时,我希望每个组件在鼠标悬停时提供一些帮助并且“?”键被按下。有点像工具提示,除了提供更广泛的帮助 - 本质上是一个小型网络浏览器,旨在弹出并显示文本、图像或更多内容。

我发现无论鼠标在哪里,输入总是转到同一个 KeyListener。一次只能激活一个吗?

不管怎样,这是现在可用的版本 - 感谢您的建议!

/** * 主类 JavaHelp 想要支持一个帮助功能,这样当 * 用户在组件上方输入 F1,它会创建一个弹窗解释 * 组件。 * 完整版旨在成为工具提示的老大哥,调用 * 带有可点击链接、嵌入图像等的 html 显示。 */ 导入 javax.swing.*; 导入 javax.swing.border.Border; 导入 java.awt.*; 导入 java.awt.event.*; 导入 java.awt.event.ActionEvent; 导入 java.awt.event.ActionListener; 导入 java.awt.event.KeyEvent; 导入 java.awt.event.KeyListener; 类 Respond2Key 扩展 AbstractAction 组件 jrp; // 合约构造器 公共 Respond2Key( 字符串文本) 超级(文本); // 确保正确完成的构造函数 public Respond2Key(字符串文本,组件 jrpIn) 超级(文本); System.out.println("用组件创建 Respond2Key" + jrpIn .toString ()); jrp = jrpIn; 公共无效setJrp(组件j) jrp = j; // 功能:对键的响应是什么 公共无效actionPerformed(ActionEvent e) // 使用 MouseInfo 获取位置,转换为窗格坐标,查找组件 点 sloc = MouseInfo.getPointerInfo().getLocation(); SwingUtilities.convertPointFromScreen(sloc, (Component) jrp); 组件 c = jrp.getComponentAt(sloc); System.out.printf("鼠标在 %5.2f,%5.2f 鼠标下的组件是 %s\n", sloc.getX(), sloc.getY(), c.toString() ); //------------------------------------------------ ---------------- // 主类 //------------------------------------------------ ---------------- 公共类 JavaHelp 扩展了 JFrame // 对象构造函数 公共 JavaHelp() // 开始构建 super("帮助系统"); this.setSize(640, 480); 容器内容 = getContentPane(); 内容.setLayout(新FlowLayout()); JButton b1 = butt("button1", 64, 48); JButton b2 = butt("button2", 96, 48); JButton b3 = butt("button3", 128, 48); JPanel p1 = 窗格(“你好”,100,100); JPanel p2 = 窗格(“世界”,200,100); 内容.add(b1); 内容.add(p1); 内容.add(b2); 内容.add(p2); 内容.add(b3); JRootPane jrp = this.getRootPane(); jrp.getInputMap(jrp.WHEN_IN_FOCUSED_WINDOW) .put(KeyStroke.getKeyStroke("F1"), "helpAction"); jrp.getActionMap().put("helpAction", 新的 Respond2Key("frame",(Component)contents) ); this.setVisible(true); this.requestFocus(); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 用于实例化和监听按钮和面板的内部类。 类 ButtonListener 实现 ActionListener 私有字符串标签 = null; 公共无效 setLabel(String s) label = s; 公共无效actionPerformed(ActionEvent e) System.out.printf("处理标记为 %s 源 %s\n\n 的事件", 标签, e.getSource().toString()); // def butt( from, name, w, h) = new Jbutton (...) 受保护的 JButton 对接(字符串 s,int w,int h) JButton b = new JButton( s ); b.setSize(w, h); ButtonListener oj = new ButtonListener(); oj.setLabel(s); b.addActionListener(oj); 返回(b); // def pane = new Jpanel(...) 受保护的 JPanel 窗格(字符串名称,int w,int h) JPanel p = 新 JPanel(); p.setMinimumSize(new Dimension(w, h)); p.add(新标签(名称)); p.setBackground(颜色.黑色); p.setForeground(Color.red); 返回(p); //-------------------------------- 公共静态无效主要(字符串 [] 参数) JavaHelp jh = new JavaHelp();

【问题讨论】:

【参考方案1】:

输入始终转到类似的 KeyListener。

KeyEvent 会不断地发送到具有中心的部分,鼠标区域会避开关键事件的创建方式。

您应该使用 Key Bindings,而不是使用 KeyListener。在您使用键绑定时,您可以通过将限制添加到 JFrame 的根表来在生成 KeyStroke 的任何时间点召唤一个动作。仔细阅读 Swing 教学练习中关于键绑定的部分以获取更多数据。

目前在您为“?”而制作的动作中那时您可以使用 KeyStroke:

利用 MouseInfo 类获取当前鼠标区域。

利用 SwingUtilities.convertPointFromScreen(...) 切换鼠标高亮与根表比较

然后,此时,您可以使用 Container.getComponentAt(...) 来获取鼠标完成的真正片段

当您知道零件时,您可以显示您的辅助数据。

【讨论】:

【参考方案2】:

我确信有更好的方法,但有一个快速而肮脏的解决方案:

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

或者,如有必要:

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

然后只需.addMouseListener(new HoverFocusListener()) 发送给所有受影响的组件。

【讨论】:

每次我悬停时都会改变焦点吗?【参考方案3】:

输入总是转到同一个 KeyListener。

一个KeyEvent总是被派发给有焦点的组件,鼠标位置与key event的产生方式无关。

您应该使用Key Bindings,而不是使用 KeyListener。当您使用键绑定时,您可以通过将绑定添加到 JFrame 的根窗格来在生成 KeyStroke 时调用操作。阅读 Key Bindings 上的 Swing 教程部分了解更多信息。

现在在您创建的用于监听“?”的操作中然后您可以使用 KeyStroke:

    使用MouseInfo 类获取当前鼠标位置。 使用SwingUtilities.convertPointFromScreen(...) 将鼠标点转换为相对于根窗格 然后您可以使用Conatiner.getComponentAt(...) 来获取鼠标所在的实际组件 一旦您了解了该组件,您就可以显示您的帮助信息。

【讨论】:

以上是关于在 java awt 或 swing 中,如何安排键盘输入到鼠标所在的位置?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用Java AWT / Swing垂直对齐面板

用于 GUI 构建的 Java AWT 或 Swing?

Java AWT/SWT/Swing:如何规划 GUI?

Java中awt和swing的关系和区别

如何解决 Java awt/swing 图像打印的滞后问题?

java swing 中的列表框JList如何在程序中动态的添加和删除元素