Java 使用键绑定和鼠标信息获取标签

Java 使用键绑定和鼠标信息获取标签,java,swing,jpanel,jlabel,key-bindings,Java,Swing,Jpanel,Jlabel,Key Bindings,这是我上一次提问的后续问题 我有两个jpanel,每个都有5个jlabel。当我将鼠标放在其中一个jlabel上并按delete键时,我想打印标签文本。以下是我尝试过的: import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.MouseInfo; import java.awt.Point; im

这是我上一次提问的后续问题

我有两个
jpanel
,每个都有5个
jlabel
。当我将鼠标放在其中一个
jlabel
上并按delete键时,我想打印标签文本。以下是我尝试过的:

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();
         }
      });
   }
}
如果我理解正确,我有一个
JPanel
(KeybindExample),它包含两个
JPanel
,这两个
JPanel
都包含
jlabel
。因此,当我使用getComponentAt(x,y)时,我得到的组件是另一个
JPanel
,这导致了类型转换的问题

我认为我需要做的是在(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。

关键问题是——如何在某个时间点(这里是按delete键时)获取对所需JLabel的引用。您当前的解决方案(我之前提出的解决方案)不起作用,因为代码找到了相对于KeybindExample JPanel的当前组件,因为这是您正在调用
getComponentAt()
方法的组件。一种可能的解决方案是在实际包含JLabel的JPanel上调用
getComponentAt()
。另一种可能的解决方案是计算鼠标相对于每个JLabel的位置,并使用
contains(…)
方法查看鼠标是否位于其中一个JLabel上。要做到这一点,您需要访问所有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.awt.BorderLayout;
导入java.awt.Dimension;
导入java.awt.FlowLayout;
导入java.awt.MouseInfo;
导入java.awt.Point;
导入java.awt.PointerInfo;
导入java.awt.event.ActionEvent;
导入java.awt.event.KeyEvent;
导入java.util.ArrayList;
导入java.util.List;
导入javax.swing.*;
@抑制警告(“串行”)
公共类KeybindExample扩展了JPanel{
私有列表标签列表=新的ArrayList();
公钥绑定示例(){
setLayout(新的BorderLayout());
添加(firstRow(),BorderLayout.NORTH);
添加(secondRow(),BorderLayout.SOUTH);
int condition=JComponent.WHEN在聚焦窗口中;
InputMap InputMap=getInputMap(条件);
ActionMap ActionMap=getActionMap();
KeyStroke delKeyStroke=KeyStroke.getKeyStroke(KeyEvent.VK_DELETE,0);
String delete=“delete”;
inputMap.put(delKeyStroke,delete);
put(delete,newdeleteAction());
}
私有类DeleteAction扩展了AbstractAction{
@凌驾
已执行的公共无效操作(操作事件evt){
PointerInfo pInfo=MouseInfo.getPointerInfo();
点ptOnScrn=pInfo.getLocation();
用于(JLabel标签:labelList){
int x=ptOnScrn.x-label.getLocationOnScreen().x;
int y=ptOnScrn.y-label.getLocationOnScreen().y;
if(标签包含(x,y)){
System.out.println(“所选标签:+Label.getText());
}
}
//int xPanel=getLocationOnScreen().x;
//int yPanel=getLocationOnScreen().y;
//intx=ptOnScrn.x-xPanel;
//int y=ptOnScrn.y-yPanel;
//
//组件=getComponentAt(x,y);
//如果(组件!=null){
//JLabel selectedLabel=(JLabel)组件;
//System.out.println(“所选标签:+selectedLabel.getText());
// }
}
}
私有JPanel firstRow(){
JPanel面板=新的JPanel(新的FlowLayout(FlowLayout.LEFT));
字符串[]x={“1”、“2”、“3”、“4”、“5”};
对于(int i=0;i<5;i++){
JLabel标签=新的JLabel(x[i]);
标签列表。添加(标签);
label.setPreferredSize(新尺寸(50,50));
面板。添加(标签);
}
返回面板;
}
私人JPanel secondRow(){
JPanel面板=新的JPanel(新的FlowLayout(FlowLayout.LEFT));
字符串[]x={“6”、“7”、“8”、“9”、“10”};
对于(int i=0;i<5;i++){
JLabel标签=新的JLabel(x[i]);
标签列表。添加(标签);
label.setPreferredSize(新尺寸(50,50));
面板。添加(标签);
}
返回面板;
}
私有静态void createAndShowGui(){
KeybindExample主面板=新建KeybindExample();
JFrame=newjframe(“键绑定示例”);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(主面板);
frame.pack();
frame.setLocationByPlatform(真);
frame.setVisible(true);
}
公共静态void main(字符串[]args){
SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
createAndShowGui();
}
});
}
}
关键问题是——当按下delete键时,如何在特定时间点获取对所需JLabel的引用。您当前的解决方案(我之前提出的解决方案)不起作用,因为代码找到了相对于KeybindExample JPanel的当前组件,因为这是您正在调用
getComponentAt()
方法的组件。一种可能的解决方案是在实际包含JLabel的JPanel上调用
getComponentAt()
。另一种可能的解决方案是计算鼠标相对于每个JLabel的位置,并使用
contains(…)
方法查看鼠标是否位于其中一个JLabel上。要做到这一点,您需要访问所有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.awt.BorderLayout;
导入java.awt.Dimension;
导入java.awt.FlowLayout;
我