2013-12-21 18 views
1

我目前正在編寫一個程序,其中有28個標籤創建並排列在for循環中的網格中,我想爲每個標籤添加一個mouseListener。我可以爲每個標籤添加一個mouseListener,但是當我嘗試指定標籤號並更改該標籤的邊框顏色時,我得到一個「從內部類訪問局部變量需要聲明爲最終」的錯誤。我明白這個錯誤背後的原因,但是我不能將「labelNum」變量作爲最終變量,因爲它在循環中需要更改。什麼是解決方法?將addMouseListener()用於數組中的每個標籤?

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)); 

        } 
       } 
    } 
} 

回答

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個MouseListeners。你的循環之前的代碼應該更像:

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次。只需在循環外讀取一次圖標並將圖標添加到每個標籤。你也不需要創建28個邊框。只需創建一次邊界並分享它。

最後,您不應該使用setBounds(...)來定位和調整標籤大小。使用適當的佈局管理器(可能是GridLayout)在網格中顯示標籤。需要

+0

哇,謝謝,非常感謝!正如你可以告訴我這個東西相當新,但這是非常有益的! – Foundry

0

「我得到一個‘局部變量是從內部類訪問被聲明爲final’的錯誤。我理解這種錯誤背後的原因,但我不能做‘因爲它需要改變labelNum’變量最後因爲它是在循環這裏有什麼解決方法解決

答案很簡單:?解決方法是爲類成員全局聲明的對象

0

簡單的解決方法:申報labelNum決賽。是的,這似乎很奇怪,但它的工作。

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

交替修復就像MJafars(使用內部類),所以我刪除它。

而且,正如我原來的(現在大部分刪除的)文章中所提到的,@Camickr有正確的解決方案來查看事件源,並且只創建一個偵聽器。

+0

當然,您可以使用內部類,但是當您只需創建單個實例並使用MouseEvent的源對象獲取JLabel來編寫泛型代碼時,您爲什麼要創建該類的28個實例? – camickr

+0

在這個特定的例子中,你是100%正確的,但是可能有其他情況下他需要這個「技巧」。 – user949300

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)); 

會工作

+0

當然,您可以使用內部類,但是當您只需創建單個實例並使用MouseEvent的源對象來獲取JLabel來編寫泛型代碼時,您爲什麼要創建該類的28個實例? – camickr

相關問題