使用几何形状作为组件

Posted

技术标签:

【中文标题】使用几何形状作为组件【英文标题】:Use geometric shapes as components 【发布时间】:2013-05-05 00:01:21 【问题描述】:

我正在尝试创建一个类似于 Paint 的应用程序,其中我必须使用一些基本形状才能创建更复杂的形状。

我将使用 Swing。我必须能够将对象从一个JEditorPane 拖放到另一个。我想使用线或圆等基元。

我想知道的是 - 原语必须是组件才能拖放它们吗?如果是这样,我怎么能做到这一点?

【问题讨论】:

可能是的,因为这个类有processMouseMotionEvent()的方法,这意味着它可以得到这样的鼠标事件和拖放工作。 【参考方案1】:

我实际上打算在这个周末写一篇关于“玩形状”的博客文章。我有一个从形状创建组件的类。该组件易于使用:

ShapeComponent component = new ShapeComponent(shape, Color.???);

这是代码的早期版本:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import javax.swing.JComponent;

/**
 *  A component that will paint a Shape object. Click detection will be
 *  determined by the Shape itself, not the bounding Rectangle of the Shape.
 *
 *  Shape objects can be created with an X/Y offset. These offsets will
 *  be ignored and the Shape will always be painted at (0, 0) so the Shape is
 *  fully contained within the component.
 *
 *  The foreground color will be used to "fill" the Shape.
 */
public class ShapeComponent extends JComponent

    private Shape shape;
    private boolean antiAliasing = true;

    /**
     *  Create a ShapeComponent that is painted black.
     *
     *  @param shape the Shape to be painted
     */
    public ShapeComponent(Shape shape)
    
        this(shape, Color.BLACK);
    

    /**
     *  Create a ShapeComponent that is painted filled and outlined.
     *
     *  @param shape the Shape to be painted
     *  @param color the color of the Shape
     */
    public ShapeComponent(Shape shape, Color color)
    
        setShape( shape );
        setForeground( color );

        setOpaque( false );
    

    /**
     *  Get the Shape of the component
     *
     *  @returns the the Shape of the compnent
     */
    public Shape getShape()
    
        return shape;
    

    /**
     *  Set the Shape for this component
     *
     *  @param shape the Shape of the component
     */
    public void setShape(Shape shape)
    
        this.shape = shape;
        revalidate();
        repaint();
    

    /**
     *  Use AntiAliasing when painting the shape
     *
     *  @returns true for AntiAliasing false otherwise
     */
    public boolean isAntiAliasing()
    
        return antiAliasing;
    

    /**
     *  Set AntiAliasing property for painting the Shape
     *
     *  @param antiAliasing true for AntiAliasing, false otherwise
     */
    public void setAntiAliasing(boolean antiAliasing)
    
        this.antiAliasing = antiAliasing;
        revalidate();
        repaint();
    

    /**
     * @inheritDoc
     */
    @Override
    public Dimension getPreferredSize()
    
        //  Include Border insets and Shape bounds

        Insets insets = getInsets();
        Rectangle bounds = shape.getBounds();

        //  Determine the preferred size

        int width = insets.left + insets.right + bounds.width;
        int height = insets.top + insets.bottom + bounds.height;

        return new Dimension(width, height);
    

    /**
     * @inheritDoc
     */
    @Override
    public Dimension getMinimumSize()
    
        return getPreferredSize();
    

    /**
     * @inheritDoc
     */
    @Override
    public Dimension getMaximumSize()
    
        return getPreferredSize();
    

    @Override
    protected void paintComponent(Graphics g)
    
        super.paintComponent(g);

        //  Graphics2D is required for antialiasing and painting Shapes

        Graphics2D g2d = (Graphics2D)g.create();

        if (isAntiAliasing())
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        //  Shape translation (ie. non-zero X/Y position in bounding rectangle)
        //  and Border insets.

        Rectangle bounds = shape.getBounds();
        Insets insets = getInsets();

        //  Do all translations at once

        g2d.translate(insets.left - bounds.x, insets.top - bounds.y);

        //  Fill the Shape

        g2d.fill( shape );

        g2d.dispose();
    

    /**
     *  Determine if the point is in the bounds of the Shape
     *
     * @inheritDoc
     */
    @Override
    public boolean contains(int x, int y)
    
        Rectangle bounds = shape.getBounds();
        Insets insets = getInsets();

        //  Check to see if the Shape contains the point. Take into account
        //  the Shape X/Y coordinates, Border insets and Shape translation.

        int translateX = x + bounds.x - insets.left;
        int translateY = y + bounds.y - insets.top;

        return shape.contains(translateX, translateY);
    

它将帮助您解决问题的组成部分。

编辑:

最新版本和完整的博客条目可以在Playing With Shapes找到。

【讨论】:

【参考方案2】:
    您可以使用JPanel作为绘制形状的区域 使用JPanel,您不能将某些形状放在后面和前面。因此,理想的选择是使用JLayeredPane,这样在绘制后您可以选择通过设置适当的 Z 顺序来前后移动形状 绘制每个新形状时,根据鼠标单击的位置在JLayeredPane 中添加一个新的JPanel。这样做可以轻松地在多个JLayeredPanes 内部和跨多个JLayeredPanes 移动形状

【讨论】:

以上是关于使用几何形状作为组件的主要内容,如果未能解决你的问题,请参考以下文章

threejs学习day3:几何形状

OpenCV-几何形状颜色识别 #导入MD文档图片#

IfcIndexedPolyCurve—加固组件案例

模块化发光组件 SMARTBUNCH:到底是玩具还是灯具?!

unity 识别哪个boxcollider

AFRAME文本几何组件从中心旋转?