6

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

我发现无论鼠标在哪里,输入总是进入同一个 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();
    }



    }





4

3 回答 3

3

输入总是转到同一个 KeyListener。

KeyEvent 总是被分派给有焦点的组件,鼠标位置与键事件的生成方式无关。

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

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

  1. 使用MouseInfo该类获取当前鼠标位置。
  2. 使用SwingUtilities.convertPointFromScreen(...)将鼠标点转换为相对于根窗格
  3. 然后您可以使用Conatiner.getComponentAt(...)来获取鼠标所在的实际组件
  4. 一旦你知道了组件,你就可以显示你的帮助信息。
于 2014-06-07T19:25:31.060 回答
3

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

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())对所有受影响的组件。

于 2014-06-07T19:18:11.393 回答
0

输入始终进入类似的 KeyListener。

一个 KeyEvent 不断地发送到具有中心的部分,鼠标区域避开了关键事件是如何创建的。

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

目前在您为“?”而制作的动作中。KeyStroke 你可以,然后,在这一点上:

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

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

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

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

于 2021-07-19T20:55:47.257 回答