如何使我没有使用的部分是简单的JComponent透明,以便在将其添加到JFrame时它不包含其他组件?

时间:2013-04-28 22:33:48

标签: java swing jframe transparent jcomponent

我在向JFrame添加2个简单组件时遇到问题。问题是,第二个组件完全覆盖第一个组件,即使每个组件只包含一个位于JFrame上的不同形状的小形状。我浏览了一段时间但找不到解决问题的方法。

public class Main
{
    public static void main(String[]args)
    {
        JFrame frame = new JFrame();
        CircleComponent comp = new CircleComponent(400,400);
        CircleComponent comp2 = new CircleComponent(200,200);

        frame.add(comp);
        frame.add(comp2);
        frame.setSize(800,800);
        frame.setVisible(true);
    }
}

//////////////////////////////////////////////////////////////////////////

public class CircleComponent extends JComponent
{
    Ellipse2D.Double ellipse;
    double x; 
    double y;
    public CircleComponent(int xx, int yy)
   {
        x = xx;
        y = yy;
        ellipse = new Ellipse2D.Double(x,y,25,25);
        setOpaque(false);
    }

   public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.fill(ellipse);
    }
}

1 个答案:

答案 0 :(得分:2)

这与可见性无关。它与布局管理器的工作方式有关。

JFrame的默认布局管理器是BorderLayout。在未指定约束的情况下向框架添加组件时,组件将添加到CENTER中。但是,只有一个组件可以添加到CENTER中,因此只有最后添加的组件才会被绘制。

您的组件代码不正确。为了绘制组件,需要具有优选的尺寸和尺寸。布局管理器将使用布局管理器的规则及其首选大小来确定大小。

您的代码恰好起作用,因为BorderLayout的CENTER规则是为组件提供所有可用空间。在你的情况下800x800(减去框架的边框)。

编辑:

  

我是否应该将组件添加到JPanel,并使用允许它们相互重叠的layoutmanager?

您仍然需要实现getPreferredSize(..)方法。首选尺寸需要考虑x / y位置以及矩形的宽度/高度。完成此操作后,您可以使用布局管理器。但是,没有提供此支持的标准布局管理器。

但是,您可以使用Overlap Layout

另一种方法是让组件始终在组件的偏移(0,0)处绘制矩形。然后,您将使用组件的setLocation(...)方法定位组件。这是在Swing中如何使用组件的更一般方法。我碰巧在几天前参加了一场我正在上课的课程。

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

此代码比您的组件更灵活,因为您可以创建圆形,矩形或任何其他形状。基本代码是:

Shape circle = new Ellipse2D.Double(0, 0, 25, 25);
ShapeComponent sc = new ShapeComponent(circle, Color.RED);
circle.setLocation(400, 400);

您还希望使用特殊布局。因此,请查看可用于组件随机位置的Drag Layout