Java – 自定义形状面板?

我正在开发一个应用程序,涉及用户需要将鼠标hover在屏幕上的几个移动点上,以便启动特定的弹出窗口。 目前,我正在JPanel上监听渲染点的mouseMoved事件,然后每当光标位于点的特定距离内时启动所需的弹出窗口。

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

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

有谁知道我如何用JComponent代表一个小椭圆?

非常感谢

这是一些旧代码,展示了如何创建“圆形”JButton。 我会改为扩展JComponent,重写的重要方法是paintComponent()和contains():

 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顺序。

你写“这可能变得相当昂贵”

无论您是自己编写“isMouseCloseToDot”方法,还是使用内置于Swing中的内容,在任何一种情况下,计算机仍然需要执行工作以确定是否激活了点。

我建议坚持使用您当前的方法,除非您已确定此方法确实过于昂贵。 用几百个点做一个小测试。 响应时间是否可以接受?

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

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

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