2010-08-09 30 views
1

我正在研究一个应用程序,该应用程序涉及用户需要将鼠标悬停在屏幕上的多个移动点上以启动特定的弹出窗口。目前,我正在侦听JPanel上的mouseMoved事件,其中渲染了点,然后在光标位于点的特定距离内时启动所需的弹出窗口。Java - 自定义形状面板?

当我有数百个点 - 这可能会变得相当昂贵。

难道理想的解决方案是将我的“小点”表示为小组件,并在每个点上注册鼠标监听器?

有谁知道我可能代表一个小的椭圆与JComponent

非常感谢

回答

1

以下是一些显示如何创建“圆形”JButton的旧代码。我将扩展JComponent的替代和重要的方法覆盖是的paintComponent()和包含():

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

    } 
} 

这很容易简化了碰撞检测,因为没有自定义代码。由于您可以控制每个组件的Z顺序,因此它还允许您轻松控制compnents的重叠。

+0

谢谢这是非常有用的! – TotalCruise 2010-08-11 08:16:55

1

您写“此可能变得相当昂贵,”不管你自己编写的“isMouseCloseToDot”方法

,或者你是否使用内置到摇摆的东西,在这两种情况下的工作仍在需要由计算机执行以确定点是否已激活。

我建议坚持你目前的做法,除非你确定这种方法确实太昂贵了。用几百个点做一个小测试。响应时间是否可以接受?

+0

这是可以接受的。我有很多很多的监听事件来执行面板上的各种对象。所以,虽然我认为swing例程会更有效率,但我还面临着一个监听器类,其中有许多搜索循环,并引用了面板上呈现的对象列表。为了简化代码的观点 - 这种方法也可以带来好处。 – TotalCruise 2010-08-09 11:08:55

0

不确定哪种方法更昂贵,但基于组件的方法肯定更容易实现。

您只需要创建自己的组件,即可覆盖paintcontains方法。将其添加到容器中的特定位置(使用绝对布局或任何其他取决于您的需要)。您的听众将成为提供组件行为的新组件的一部分。

从设计和程序组织的角度来看,这是更优越的方法。