【问题标题】:Clicking on a drawn object单击绘制的对象
【发布时间】:2012-10-07 16:02:07
【问题描述】:

我有一个名为 Shape 的类,它继承自 JPanel。

许多子类依次扩展Shape 类,每个子类对应一种形状。

每个形状都有自己的重写paint() 方法,用于绘制各自的形状。

我希望能够单击任何形状,并且现在正在尝试实现此逻辑。请注意,每个形状都已添加到 arrayList。

但是,包含语句总是返回 false,即使我已经清楚地点击了形状。

有什么想法吗?

【问题讨论】:

  • 好的,你在计划像Paint Shapes组件这样的东西吗?
  • 什么样的形状?您必须实现 contains 方法。它不会从他们的“绘画”方法中生成。
  • 您能否详细说明@JanDvorak?到目前为止,该程序可以工作,从而在屏幕上绘制了许多形状。我的问题是我似乎无法点击任何形状。
  • 看看 MouseListener 或 SwingUtilities
  • 在你的 swift 范围内是 SSCCE 超过要求,或者我无用地开玩笑关于尊重论坛习惯(当然也错了),没有人可以看到你的其余代码,潜在的回答者简单地忽略了这一点问题(有几个很好的答案,能够不假思索地回答这个问题),

标签: java swing graphics jpanel paintcomponent


【解决方案1】:

永远不要在 JPanel 中覆盖 paint() 而不是 paintComponent(..)

我不太确定我是否理解,但是我做了一个简短的示例,希望对您有所帮助。 基本上它是一个简单的JFrameDrawingPanel(我自己的类扩展了JPanel 并绘制了形状)。此面板将创建形状(仅 2 个用于测试)将它们添加到 ArrayList 并通过 paintComponent(..)for 循环将它们绘制到 JPanel,它还有一个 MouseAdapter 用于检查用户 @987654333 @evnets 在JPanel 上。当单击时,我们遍历ArrayList 中的每个Shape 并检查Shape 是否包含该点,如果是,则打印其类名并使用instance of 检查Shape 的类型被点击并打印相应的消息:

输出(点击两个形状后):

点击了一个 java.awt.geom.Rectangle2D$Double

点击了一个矩形

点击了一个 java.awt.geom.Ellipse2D$Double

点击了一个圆圈

ShapeClicker.java:

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ShapeClicker {

    public ShapeClicker() {
        JFrame frame = new JFrame();
        frame.setTitle("Shape Clicker");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);

        initComponents(frame);

        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {

        //create frame and components on EDT
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new ShapeClicker();
            }
        });
    }

    private void initComponents(JFrame frame) {
        frame.add(new ShapePanel());
    }
}

//custom panel
class ShapePanel extends JPanel {

    private Shape rect = new Rectangle2D.Double(50, 100, 200, 100);
    private Shape cirlce = new Ellipse2D.Double(260, 100, 100, 100);
    private Dimension dim = new Dimension(450, 300);
    private final ArrayList<Shape> shapes;

    public ShapePanel() {
        shapes = new ArrayList<>();
        shapes.add(rect);
        shapes.add(cirlce);
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent me) {
                super.mouseClicked(me);
                for (Shape s : shapes) {
                    
                    if (s.contains(me.getPoint())) {//check if mouse is clicked within shape
                        
                        //we can either just print out the object class name
                        System.out.println("Clicked a "+s.getClass().getName());
                        
                        //or check the shape class we are dealing with using instance of with nested if
                        if (s instanceof Rectangle2D) {
                            System.out.println("Clicked a rectangle");
                        } else if (s instanceof Ellipse2D) {
                            System.out.println("Clicked a circle");
                        }
                        
                    }
                }
            }
        });
    }

    @Override
    protected void paintComponent(Graphics grphcs) {
        super.paintComponent(grphcs);
        Graphics2D g2d = (Graphics2D) grphcs;
        for (Shape s : shapes) {
            g2d.draw(s);
        }
    }

    @Override
    public Dimension getPreferredSize() {
        return dim;
    }
}

【讨论】:

  • 它没有解决问题,但我非常感谢您的努力。谢谢:)
【解决方案2】:

如果您要实现Shape,您必须自己实现contains 方法。 Shape 的默认实现总是返回 false

如果您的Shape 以您知道如何相交的曲线为界(或确定一个点是在一侧还是另一侧),您可以使用even-odd rule。从测试点向任何不平行于直线的方向投射光线。如果交叉点的数量是奇数,则该点在内部。如果交叉点的数量是偶数,则该点在外面。

内置类实现此方法,因此您可以使用/扩展PolygonEllipse2D.DoubleRoundRectangle2D.Double 类,并拥有一个知道其内部的填充多边形/椭圆/圆角矩形。

【讨论】:

  • 感谢您的回复。由于我的形状类调用了 draw 方法并绘制了这样的形状,它们并没有真正与形状类绑定是吗?
  • @DotNET 你说你有一个shapeArrayList?因此,如果您实现 contains 方法,您尝试过的方法将起作用。
  • 我明白了,非常感谢。不过,我不太确定如何实现 contains 方法。这应该是一个涵盖 Java 基础知识的非常简单的作业,但是您提到的内容似乎很复杂,超出了本任务的范围。
  • @JanDvorak Shape 是一个接口并已实现 - 未扩展。可能会让未来的读者感到困惑。修复后 +1。
猜你喜欢
  • 2017-03-27
  • 1970-01-01
  • 2022-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多