2013-04-08 77 views
1

我正在創建一個簡單的遊戲,其中一個人點擊圖像的分數會增加1。 這似乎很簡單,對吧?這就是抓拍 - 圖像將部分隱藏在其他圖像之後!Java ImageIcons和actioin聽衆

目前,我用幾個imageIcons設置我的場景。例如,我的前景有一個圖像「foreground.png」,我的背景是「background.png」,隱藏在兩者之間的圖像是「hiding.png」。

我首先想到的是簡單地讓ImageIcon的隱藏的座標,高度()和寬度()添加到它們,並創建一個鼠標偵聽器,將只在指定的區域工作。但是,這會給我一個矩形,讓用戶單擊它來打破隱藏對象的目的(某人可以單擊前景背景中圖形的剛性邊界)。

你有關於如何使只有一個ImageIcon的可見光像素鼠標動作偵聽器的工作有什麼建議?是的,我明白,動作偵聽器只能應用於組件(如按鈕),但「按鈕」只是沒有做我想要的這個項目。

+2

這取決於你是如何呈現的圖像。如果您使用'JLabel',您可以根據組件Layout的Z-Order將一個鼠標監聽器附加到'JLabel',那麼您只能點擊標籤的可見區域(如上圖所示會消耗它) – MadProgrammer 2013-04-08 04:54:55

+0

我可以在圖像後面繪製JLabel(我覆蓋paintComponent()以繪製前景和背景)? – JavaJew22 2013-04-08 05:00:44

+0

你關心透明度嗎? – MadProgrammer 2013-04-08 05:07:40

回答

5

實施例1

這基本上使用上的JLayeredPane一系列JLabel秒。每個標籤都有它自己的鼠標監聽器,當你將鼠標放在它上面時,它會變成紅色。但是,如果有它上面的標籤,也不會響應鼠標事件...

enter image description here

import java.awt.AlphaComposite; 
import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import javax.imageio.ImageIO; 
import javax.swing.Icon; 
import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JLayeredPane; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class ClickMyImages { 

    public static void main(String[] args) { 
     new ClickMyImages(); 
    } 

    public ClickMyImages() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JLayeredPane { 

     public TestPane() { 
      try { 
       BufferedImage img1 = ImageIO.read("/Image1"); 
       BufferedImage img2 = ImageIO.read("/Image2"); 
       BufferedImage img3 = ImageIO.read("/Image3"); 
       BufferedImage img4 = ImageIO.read("/Image4"); 
       BufferedImage img5 = ImageIO.read("/Image5"); 

       JLabel label1 = new ClickableLabel(new ImageIcon(img1)); 
       JLabel label2 = new ClickableLabel(new ImageIcon(img2)); 
       JLabel label3 = new ClickableLabel(new ImageIcon(img3)); 
       JLabel label4 = new ClickableLabel(new ImageIcon(img4)); 
       JLabel label5 = new ClickableLabel(new ImageIcon(img5)); 

       Dimension masterSize = getPreferredSize(); 

       Dimension size = label1.getPreferredSize(); 
       label1.setBounds((masterSize.width - size.width)/2, (masterSize.height - size.height)/2, size.width, size.height); 
       Point masterPoint = label1.getLocation(); 
       size = label2.getPreferredSize(); 
       label2.setBounds(
         masterPoint.x - (size.width/2), 
         masterPoint.y - (size.height/2), 
         size.width, size.height); 
       size = label3.getPreferredSize(); 
       label3.setBounds(
         masterPoint.x + (size.width/2), 
         masterPoint.y - (size.height/2), 
         size.width, size.height); 
       size = label4.getPreferredSize(); 
       label4.setBounds(
         masterPoint.x - (size.width/2), 
         masterPoint.y + (size.height/2), 
         size.width, size.height); 
       size = label5.getPreferredSize(); 
       label5.setBounds(
         masterPoint.x + (size.width/2), 
         masterPoint.y + (size.height/2), 
         size.width, size.height); 

       add(label1); 
       add(label2); 
       add(label3); 
       add(label4); 
       add(label5); 

      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(800, 800); 
     } 
    } 

    // This is for demonstration purposes only! 
    public class ClickableLabel extends JLabel { 

     private boolean isIn = false; 

     public ClickableLabel(Icon image) { 
      super(image); 
      addMouseListener(new MouseAdapter() { 
       @Override 
       public void mouseEntered(MouseEvent e) { 
        isIn = true; 
        repaint(); 
       } 

       @Override 
       public void mouseExited(MouseEvent e) { 
        isIn = false; 
        repaint(); 
       } 
      }); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      if (isIn) { 
       Graphics2D g2d = (Graphics2D) g.create(); 
       g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f)); 
       g2d.setColor(Color.RED); 
       g2d.fillRect(0, 0, getWidth(), getHeight()); 
       g2d.dispose(); 
      } 
     } 
    } 
} 

實施例2

下面的例子使用的paintComponent方法來渲染器圖片。它檢查鼠標點處圖像的像素阿爾法,以確定鼠標事件是否應該通過。

我已經有點嚴格使用255的α值,但你可以軟化了一點根據您的需要(像225,而不是爲例)...

我硬編碼的使樹始終位於松鼠上方,但按照您希望它們出現的順序將所有圖像添加到List並不難,並且簡單地沿着列表運行直到您獲得命中。

enter image description here

import java.awt.AlphaComposite; 
import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Composite; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.Rectangle; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class ClickMyDrawnImages { 

    public static void main(String[] args) { 
     new ClickMyDrawnImages(); 
    } 

    public ClickMyDrawnImages() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private BufferedImage tree; 
     private BufferedImage squirrel; 
     private BufferedImage mouseOver; 

     public TestPane() { 
      try { 
       tree = ImageIO.read(new File("Tree.png")); 
       squirrel = ImageIO.read(new File("Squirrel.png")); 
      } catch (IOException exp) { 
       exp.printStackTrace(); 
      } 
      addMouseMotionListener(new MouseAdapter() { 
       @Override 
       public void mouseMoved(MouseEvent e) { 
        if (withinTree(e.getPoint())) { 
         mouseOver = tree; 
        } else if (withinSquirrel(e.getPoint())) { 
         mouseOver = squirrel; 
        } else { 
         mouseOver = null; 
        } 
        repaint(); 
       } 
      }); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     protected boolean withinTree(Point p) { 
      return withinBounds(p, getTreeBounds(), tree); 
     } 

     protected boolean withinSquirrel(Point p) { 
      return !withinBounds(p, getTreeBounds(), tree) && withinBounds(p, getSquirrelBounds(), squirrel); 
     } 

     protected Rectangle getTreeBounds() { 
      int width = getWidth(); 
      int height = getHeight(); 

      int x = (width - tree.getWidth())/2; 
      int y = (height - tree.getHeight())/2; 

      return new Rectangle(x, y, tree.getWidth(), tree.getHeight()); 
     } 

     protected Rectangle getSquirrelBounds() { 
      Rectangle bounds = getTreeBounds(); 

      return new Rectangle(
        bounds.x - (squirrel.getWidth()/4), 
        (getHeight() - squirrel.getHeight())/2, 
        squirrel.getWidth(), squirrel.getHeight()); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      int width = getWidth(); 
      int height = getHeight(); 

      int x = (width - tree.getWidth())/2; 
      int y = (height - tree.getHeight())/2; 

      g.drawImage(highlight(squirrel), x - (squirrel.getWidth()/4), (height - squirrel.getHeight())/2, this); 
      g2d.drawImage(highlight(tree), x, y, this); 

      g2d.dispose(); 
     } 

     protected BufferedImage highlight(BufferedImage img) { 
      BufferedImage highlight = img; 
      if (img.equals(mouseOver)) { 
       highlight = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB); 
       Graphics2D g2d = highlight.createGraphics(); 
       g2d.setColor(Color.RED); 
       g2d.drawImage(img, 0, 0, this); 

       g2d.setComposite(AlphaComposite.SrcAtop.derive(0.5f)); 
       g2d.fillRect(0, 0, highlight.getWidth(), highlight.getHeight()); 
       g2d.dispose(); 
      } 
      return highlight; 
     } 

     protected boolean withinBounds(Point p, Rectangle bounds, BufferedImage image) { 
      boolean withinBounds = false; 
      if (bounds.contains(p)) { 
       int x = p.x - bounds.x; 
       int y = p.y - bounds.y; 
       int pixel = image.getRGB(x, y); 
       int a = (pixel >> 24) & 0xFF; 
       // could use a little weighting, so translucent pixels can be effected 
       if (a == 255) { 
        withinBounds = true; 
       } 
      } 
      return withinBounds; 
     } 
    } 
} 
+0

非常感謝!這正是想要做的 – JavaJew22 2013-04-08 05:20:28

+0

+1,很酷的例子。 – camickr 2013-04-08 05:58:13

+0

@ JavaJew22我已經更新以包含一個自定義繪圖示例。 – MadProgrammer 2013-04-08 05:59:51