2010-10-31 46 views
2

我的监控是在paintComponent()方法中使用2D图形绘制多个图像。但是,我不确定如何添加MouseListener,以便每个图像都知道它是否被选中。图像映射像Java swing中的功能,点vs GeneralPath

我到目前为止的解决方案太简单地记录鼠标点击的坐标,看看它们是否包含在每个图像的边界内。但是,对于具有更复杂边界的图像来说,这将很困难。

另一种选择是创建简单的形状并将它们放置在图像上,但是具有更复杂边界的图像将很困难。在关于SO的另一个讨论中发现了 here,有人提到使用GeneralPath绘制更复杂的形状。我从来没有玩过,但这似乎令人鼓舞。

这两个选项中,似乎是最好的解决办法,还是有其他的建议

回答

2

你画在彼此顶部图像或者他们单独绘制。

如果它们分开绘制,那么您应该在JComponent上进行自定义绘制。然后你可以使用GeneralPath来完成绘图。您还需要通过检查GeneralPath中是否包含鼠标单击来实现contains(...)方法。如果contains()方法正确实现,那么MouseListener将正确响应。

下面是一个简单的例子:

import java.awt.*; 
import java.awt.event.*; 
import java.awt.geom.*; 
import javax.swing.*; 

public class RoundButton extends JButton { 
    public RoundButton(String label) { 
     super(label); 

     // These statements enlarge the button so that it 
     // becomes a circle rather than an oval. 
     Dimension size = getPreferredSize(); 
     size.width = size.height = Math.max(size.width, size.height); 
     setPreferredSize(size); 

     // This call causes the JButton not to paint the background. 
     // This allows us to paint a round background. 
     setContentAreaFilled(false); 
    } 

    // Paint the round background and label. 
    protected void paintComponent(Graphics g) { 
    if (getModel().isArmed()) { 
      // You might want to make the highlight color 
      // a property of the RoundButton class. 
      g.setColor(Color.lightGray); 
     } else { 
      g.setColor(getBackground()); 
     } 
    g.fillOval(0, 0, getSize().width-1, getSize().height-1); 

     // This call will paint the label and the focus rectangle. 
    super.paintComponent(g); 
    } 

    // Paint the border of the button using a simple stroke. 
    protected void paintBorder(Graphics g) { 
     g.setColor(getForeground()); 
     g.drawOval(0, 0, getSize().width-1, getSize().height-1); 
    } 

    // Hit detection. 
    Shape shape; 
    public boolean contains(int x, int y) { 
     // If the button has changed size, make a new shape object. 
     if (shape == null || !shape.getBounds().equals(getBounds())) { 
      shape = new Ellipse2D.Float(0, 0, getWidth(), getHeight()); 
     } 
     return shape.contains(x, y); 
    } 

    // Test routine. 
    public static void main(String[] args) { 
     // Create a button with the label "Jackpot". 
     JButton button = new RoundButton("Jackpot"); 
     button.setBackground(Color.green); 
     button.setBounds(0, 0, 100, 100); 

     JButton button2 = new RoundButton("Jackpot2"); 
     button2.setBackground(Color.red); 
     button2.setBounds(50, 50, 100, 100); 

     // Create a frame in which to show the button. 
     JFrame frame = new JFrame(); 
     frame.getContentPane().setBackground(Color.yellow); 
     frame.getContentPane().setLayout(null); 
     frame.getContentPane().add(button); 
     frame.getContentPane().add(button2); 
//  frame.getContentPane().setLayout(new FlowLayout()); 
     frame.setSize(200, 200); 
     frame.setVisible(true); 

     MouseListener mouseListener = new MouseAdapter() { 
      public void mouseEntered(MouseEvent e) 
      {} 

      public void mouseExited(MouseEvent e) 
      {} 

      public void mouseClicked(MouseEvent e) 
      { 
       System.out.println("clicked "); 
      } 

      public void mousePressed(MouseEvent e) 
      { 
       System.out.println("pressed "); 
      } 

      public void mouseReleased(MouseEvent e) 
      { 
       System.out.println("released "); 
      } 
     }; 
     button.addMouseListener(mouseListener); 

    } 
} 
+0

这看起来像它应该工作。关于您是否将图像绘制在彼此之上的问题......我希望在一个paintComponent()方法中绘制大约7-8张图像。这将需要7-8个contains()方法。难道我不能单独拥有各自具有自己形状的类来实现此目的,而不是将图像本身分开吗?谢谢。 – Koop 2010-10-31 04:22:34

+0

你应该有独立的组件,这样每个组件都可以有自己的形状。然后,只需将这些“形状组件”添加到面板中,就如同使用其他任何Swing组件一样。如果组件不分层,处理起来会更容易。但是,组件可以分层,但请记住,根据组件的ZOrder,只有顶部的组件才会收到鼠标事件。 – camickr 2010-10-31 15:25:35