How can I put 2 java swing elements on top of each other?

落爺英雄遲暮 提交于 2019-12-25 01:34:08

问题


so I have this project that I'm doing, which draws a circle and a square, and resizes them through buttons. Everything works great, however what I must do is put the circle inside the square, so that the circle is inscribed, and I can't seem to figure out how to put both swing elements on top of each other. Here's a picture of how it currently is:

And here's a photoshop version of how it should look like:

Here's my Circle class:

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;

public class Picture extends Canvas implements VetoableChangeListener, PropertyChangeListener {
    private final int SIZE = 100;
    private int radius = 1;

    public Picture() {
        setSize(SIZE,SIZE);
    }

    public void vetoableChange(PropertyChangeEvent pce) throws PropertyVetoException {
        if ((pce.getPropertyName()).equals("value")) {
            int v = (Integer)pce.getNewValue();
            if ((v <=0)||(v > SIZE/2))
                throw new PropertyVetoException ("Value out of bounds!", pce);        
        }   
    }


    public void propertyChange(PropertyChangeEvent pce) {
        if ((pce.getPropertyName()).equals("value")) {
            setRadius((Integer)pce.getNewValue());
            repaint(); 
        }
    }

    public void setRadius(int radius) {
        this.radius = radius;
    }

    public int getRadius() {
        return this.radius;
    }

    public void paint (Graphics g) {
        Dimension d = getSize();
        g.setColor(Color.GREEN);
        g.fillOval(d.width/2 - radius, d.height/2 - radius, radius*2, radius*2);
    }

}

And here's my Square class, which is similar:

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;


public class Square extends Canvas implements VetoableChangeListener, PropertyChangeListener {
    private final int SIZE = 100;
    private int side = 1;
    public Square() {
        setSize(SIZE,SIZE);
    }

    public void vetoableChange(PropertyChangeEvent pce) throws PropertyVetoException {
        if ((pce.getPropertyName()).equals("value")) {
            int v = (Integer)pce.getNewValue();
            if ((v <=0)||(v > SIZE/2))
                throw new PropertyVetoException ("Value out of bounds!", pce);        
        }   
    }

    public void propertyChange(PropertyChangeEvent pce) {
        if ((pce.getPropertyName()).equals("value")) {
            setSide((Integer)pce.getNewValue());
            repaint();
        }
    }

    public void setSide(int side) {
        this.side = side;
    }

    public int getSide() {
        return this.side;
    }

    public void paint (Graphics g) {
        Dimension d = getSize();
        g.setColor(Color.BLUE);
        g.drawRect(d.width/2 - side, d.height/2 - side, side*2, side*2);
    }

}

I've added both of them to the palette. Would you please explain to me how to put those both elements on top of each other, I'm new to Swing and JavaBeans.

Thanks in advance!


回答1:


First of all you should not be extending Canvas, that is an AWT component. In Swing you can extend JComponent (or JPanel) and then you add custom painting to the paintComponent(...) method. Read the section from the Swing tutorial on Custom Painting for more information.

Also you should make each component transparent (by using setOaque(false) in the constructor of the component so that the background of one component does not cover the other.

I've added both of them to the palette.

And they both display on top of the palette because of the rules of the layout manager being used:

So you have a couple of options:

  1. Take advantage of Swings parent/child relationship. That is add the square to the palette and the circle to the square. This means you will need to set a layout manager on the square so you can add the circle to it. A BorderLayout might be easy to use.

  2. Create a panel using the OverlayLayout. This layout manager allows you to add two components on top of one another in the same panel. You would add the square to the panel and the circle to the panel (in that order since Swing paints the last component added to a panel first).

  3. A completely different (and probably easier) option is to have a single component and paint both the square and circle in the paintComponent() method.




回答2:


You should at least override isOpaque to return false on both Circle and Square thus non-painted pixel will be considered as "show-through".

Next you also need to use a free layout in the container to be able to control exact location of your objects.

Note: don't use Canvas, it would be much better not to subclass any component to represent drawings, just implements some method (say draw) that would take a graphics to draw with, and override paintComponent of your container to call that method on every drawing object:

class Circle implements Drawable {
    int x; int y; int radius;
    public void draw(Graphics g) {
        g.fillOval(x - radius, y - radius, radius*2, radius*2);
    }
}

class MyContainer extends JPanel {
    List<Drawable> ld = ...
    public void paintComponent(Graphics g) {
        for (Drawable d : ld) {
            d.draw(g);
        }
    }


来源:https://stackoverflow.com/questions/49864848/how-can-i-put-2-java-swing-elements-on-top-of-each-other

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!