【问题标题】:Java - Custom Shape Panels?Java - 自定义形状面板?
【发布时间】:2010-08-09 10:26:44
【问题描述】:

我正在开发一个应用程序,该应用程序涉及用户需要将鼠标悬停在屏幕上的几个移动点上才能启动特定的弹出窗口。目前,我正在侦听JPanel 上的mouseMoved 事件,点被渲染到该事件上,然后只要光标在点的特定距离内,就会启动所需的弹出窗口。

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

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

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

非常感谢

【问题讨论】:

    标签: java swing jpanel


    【解决方案1】:

    这里是一些旧代码,展示了如何创建“圆形”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-Order。

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

      • 可以接受。我有很多很多的监听事件要对面板上的各种对象执行。所以,虽然我假设摇摆程序会更有效,但我也面临着一个监听器类,它到处都有几十个搜索循环,并且对面板上呈现的对象列表的引用。从代码简洁的角度来看 - 这种方法也可以带来好处。
      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-05
        • 2015-06-21
        • 1970-01-01
        相关资源
        最近更新 更多