java - 使用 Keybind 和 MouseInfo 获取 Label

标签 java swing jpanel jlabel key-bindings

这是我之前 question. 的后续问题

我有两个 JPanels,每个有 5 个 JLabels。当我将鼠标悬停在其中一个 JLabels 上并按下删除键时,我想打印标签的文本。这是我尝试过的:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.*;

@SuppressWarnings("serial")
public class KeybindExample extends JPanel {

   public KeybindExample() {
      setLayout(new BorderLayout());
      add(firstRow(), BorderLayout.NORTH);
      add(secondRow(),BorderLayout.SOUTH);
      int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
      InputMap inputMap = getInputMap(condition);
      ActionMap actionMap = getActionMap();

      KeyStroke delKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);
      String delete = "delete";

      inputMap.put(delKeyStroke, delete);
      actionMap.put(delete, new DeleteAction());
   }

   private class DeleteAction extends AbstractAction {
      @Override
      public void actionPerformed(ActionEvent evt) {
         PointerInfo pInfo = MouseInfo.getPointerInfo();
         Point ptOnScrn = pInfo.getLocation();
         int xPanel = getLocationOnScreen().x;
         int yPanel = getLocationOnScreen().y;
         int x = ptOnScrn.x - xPanel;
         int y = ptOnScrn.y - yPanel;

         Component component = getComponentAt(x, y);
         if (component != null) {
             JLabel selectedLabel = (JLabel) component;
             System.out.println("Selected Label: " + selectedLabel.getText());
          }
      }
   }
   private static JPanel firstRow(){
        JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        String [] x = {"1","2","3","4","5"};
        for(int i = 0; i < 5; i++){
            JLabel label = new JLabel(x[i]);
            label.setPreferredSize(new Dimension(50,50));
            panel.add(label);
        }

        return panel;
   }
   private static JPanel secondRow(){
        JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        String [] x = {"6","7","8","9","10"};
        for(int i = 0; i < 5; i++){
            JLabel label = new JLabel(x[i]);
            label.setPreferredSize(new Dimension(50,50));
            panel.add(label);
        }

        return panel;
   }

   private static void createAndShowGui() {
      KeybindExample mainPanel = new KeybindExample();

      JFrame frame = new JFrame("Key Bindings Example");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

我收到以下错误:

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: javax.swing.JPanel cannot be cast to javax.swing.JLabel

如果我理解正确的话,我有一个 JPanel(KeybindExample),它包含两个 JPanel,而这两个 JPanel 中的每一个包含 JLabels。因此,当我执行 getComponentAt(x,y) 时,我得到的组件是另一个导致类型转换问题的 JPanel

我认为我需要做的是获取 Component At (x,y) 的组件,这将是一个 JLabel。换句话说,我需要更进一步。我尝试了以下方法,但它仅适用于顶部面板,有时仍会返回相同的错误。

     Component component = getComponentAt(x, y);
     if (component != null) {
        JPanel selectPanel = (JPanel) component;
        Component comp = selectPanel.getComponentAt(x,y);

        if(comp != null){
           JLabel selectLabel = (JLabel) comp;
           System.out.println("Selected Label: " + selectLabel.getText());
        }
     }
  }

我怎样才能拥有包含多个 JLabel 的多个 JPanel,但能够让 JLabel 将鼠标悬停在文本上。

最佳答案

关键问题是——如何在某个时间点获取对所需 JLabel 的引用,此时您按下删除键。您当前的解决方案(我之前提出的解决方案)不起作用,因为代码找到了相对于 KeybindExample JPanel 的当前组件,因为这是您调用的组件 getComponentAt()方法上。一种可能的解决方案是调用 getComponentAt()在实际持有 JLabel 的 JPanel 上。另一种可能的解决方案是计算鼠标相对于每个 JLabel 的位置,并使用 contains(...)方法来查看鼠标是否位于 JLabel 之一上。为此,您需要有权访问所有 J​​Label,或许可以将它们放在 List<JLabel> 中。 .例如……

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;

@SuppressWarnings("serial")
public class KeybindExample extends JPanel {
   private List<JLabel> labelList = new ArrayList<>();

   public KeybindExample() {
      setLayout(new BorderLayout());
      add(firstRow(), BorderLayout.NORTH);
      add(secondRow(), BorderLayout.SOUTH);
      int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
      InputMap inputMap = getInputMap(condition);
      ActionMap actionMap = getActionMap();

      KeyStroke delKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);
      String delete = "delete";

      inputMap.put(delKeyStroke, delete);
      actionMap.put(delete, new DeleteAction());
   }

   private class DeleteAction extends AbstractAction {
      @Override
      public void actionPerformed(ActionEvent evt) {
         PointerInfo pInfo = MouseInfo.getPointerInfo();
         Point ptOnScrn = pInfo.getLocation();

         for (JLabel label : labelList) {
            int x = ptOnScrn.x - label.getLocationOnScreen().x;
            int y = ptOnScrn.y - label.getLocationOnScreen().y;

            if (label.contains(x, y)) {
               System.out.println("Selected Label: " + label.getText());
            }

         }
         // int xPanel = getLocationOnScreen().x;
         // int yPanel = getLocationOnScreen().y;
         // int x = ptOnScrn.x - xPanel;
         // int y = ptOnScrn.y - yPanel;
         //
         // Component component = getComponentAt(x, y);
         // if (component != null) {
         // JLabel selectedLabel = (JLabel) component;
         // System.out.println("Selected Label: " + selectedLabel.getText());
         // }
      }
   }

   private JPanel firstRow() {
      JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
      String[] x = { "1", "2", "3", "4", "5" };
      for (int i = 0; i < 5; i++) {
         JLabel label = new JLabel(x[i]);
         labelList.add(label);
         label.setPreferredSize(new Dimension(50, 50));
         panel.add(label);
      }

      return panel;
   }

   private JPanel secondRow() {
      JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
      String[] x = { "6", "7", "8", "9", "10" };
      for (int i = 0; i < 5; i++) {
         JLabel label = new JLabel(x[i]);
         labelList.add(label);
         label.setPreferredSize(new Dimension(50, 50));
         panel.add(label);
      }

      return panel;
   }

   private static void createAndShowGui() {
      KeybindExample mainPanel = new KeybindExample();

      JFrame frame = new JFrame("Key Bindings Example");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

关于java - 使用 Keybind 和 MouseInfo 获取 Label,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25024996/

相关文章:

java - 读取环境变量失败

java - 使用 Hibernate 创建带有一额外列的临时表

java - 如何从 java 文件对话框获取值并将其传递给变量?

java - JPanel&JScrollPane及错误渲染

java - 将 JScrollPane 添加到覆盖的 JPanel

Java 类/包,允许包装运行长操作并超时运行

java - 投影矩阵 OpenGL/GLSL 问题

java - 通过菜单使用 JApplet

java - 在表/树表上搜索按键

java - 在一个 JPanel 上绘图