使用addMouseListener()到数组中的每个标签?

时间:2013-12-21 16:28:56

标签: java swing mouselistener

我目前正在编写一个程序,在for循环中创建并排列了28个标签,我希望为每个标签添加一个mouseListener。我可以为每个标签添加一个mouseListener,但是当我尝试指定标签号并更改该标签的边框颜色时,我得到一个“从内部类访问本地变量需要声明为final”错误。我理解这个错误背后的原因,但我不能让“labelNum”变量最终,因为它需要改变,因为它在循环中。什么是解决方案解决方案?

for (int c = 0; c < 7; c++) {
    for (int d = 0; d < 4; d++) {
                labelNum = c*4+d;
                inventorySlotLabels[labelNum] = new JLabel();
                inventorySlotLabels[labelNum].setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
                inventorySlotLabels[labelNum].setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
                inventorySlotLabels[labelNum].setBounds(15+d*40+d*10, 15+c*30+c*10, 40, 30);
                inventorySlotLabels[labelNum].setIcon(new javax.swing.ImageIcon(getClass().getResource("Item.png")));

                inventorySlotLabels[labelNum].addMouseListener(new java.awt.event.MouseAdapter() {
                    public void mouseClicked(java.awt.event.MouseEvent evt) {
                        headerLabel.setText("Inventory Slot Clicked");
                        inventorySlotLabels[labelNum].setBorder(BorderFactory.createLineBorder(Color.WHITE));

                    }
                }
    }
}

4 个答案:

答案 0 :(得分:2)

public void mouseClicked(java.awt.event.MouseEvent evt) 
{
    headerLabel.setText("Inventory Slot Clicked");
    inventorySlotLabels[labelNum].setBorder(BorderFactory.createLineBorder(Color.WHITE));
}

不要依赖标签号变量。从MouseEvent获取标签:

public void mouseClicked(java.awt.event.MouseEvent evt) 
{
    headerLabel.setText("Inventory Slot Clicked");
    //inventorySlotLabels[labelNum].setBorder(BorderFactory.createLineBorder(Color.WHITE));
    JLabel label = (JLabel)evt.getSource();
    label.setBorder( ... );
}

编辑:

实际上,没有理由创建28个MouseListener。在循环之前,代码应该更像:

MouseListener ml = new MouseListener()
{
    public void mouseClicked(java.awt.event.MouseEvent evt) 
    {
        headerLabel.setText("Inventory Slot Clicked");
        //inventorySlotLabels[labelNum].setBorder(BorderFactory.createLineBorder(Color.WHITE));
        JLabel label = (JLabel)evt.getSource();
        label.setBorder( ... );
    }
};

然后在你的循环中你只需使用:

inventorySlotLabels[labelNum].addMouseListener( ml );

无论是使用annoymouse内部类还是内部类,更好的设计方法是使用MouseEvent中的源对象,不需要创建28个MouseListener来存储变量来索引Array中的标签。实际上,当您使用这种方法时甚至不需要保留数组,这将进一步简化您的代码,因为现在您不再局限于硬编码值来确定数组的大小。

此外,无需阅读图标28次。只需在循环外读取一次Icon,并将Icon添加到每个标签。您也不需要创建28个边框。只需创建一次边框并分享即可。

最后,您不应该使用setBounds(...)来定位和调整标签大小。使用适当的布局管理器(可能是GridLayout)在网格中显示标签。

答案 1 :(得分:0)

  

“我得到一个”从内部类访问本地变量需要被声明为final“错误。我理解这个错误背后的原因,但我不能让”labelNum“变量最终,因为它需要改变自它在循环中。这里的解决方案是什么?

简单回答:解决方法是将对象全局声明为类成员

答案 2 :(得分:0)

简单修复:声明labelNum final。是的,这看起来很奇怪,但它确实有效。

for (int c = 0; c < 7; c++) {
  for (int d = 0; d < 4; d++) {
    final int labelNum = c*4+d;
    ...

替代修复就像MJafars(使用内部类)所以我删除了它。

而且,正如我原来(现已大部分删除)帖子所述,@ Camick有适当的解决方案,查看事件源,只创建一个监听器。

答案 3 :(得分:0)

为什么匿名的内部课程?使用一个简单的内部类!

class InventoryMouseListener extends java.awt.event.MouseAdapter {
     private int labelNum;
     public InventoryMouseListener(int labelNum) {
         this.labelNum = labelNum;
     }
     @Override
     public void mouseClicked(java.awt.event.MouseEvent evt) {
         headerLabel.setText("Inventory Slot Clicked");
         inventorySlotLabels[labelNum].setBorder(BorderFactory.createLineBorder(Color.WHITE));
     }
}

添加侦听器

inventorySlotLabels[labelNum]
   .addMouseListener(new InventoryMouseListener(labelNum));

会起作用