简体   繁体   中英

Clicking on a JPanel to draw shapes

I have a JFrame containing 3 JPanels; Options, menu, canvas. In options there are a number of JButtons representing shapes. The aim is to click on the JButton of a shape eg rectangle, then click anywhere on the canvas and the shape will be drawn there. For some reason, the shape does not always get drawn, it is only drawn when I click somewhere in the top left area of the canvas. Also the shape seems to randomly change size depending on where I click.

Here are some of my code snippets, it's probably a small error but I just can't seem to find it.

Shape:

public class Shape extends JPanel {

    protected int xLocation;
    protected int yLocation;
    protected int numberOfSides; 
    protected String areaInfo; 
    protected String perimeterInfo; 

    public int getXLocation() {
        return xLocation;
    }

    public void setXLocation(int xLocation) {
        this.xLocation = xLocation;
    }

    public int getYLocation() {
        return yLocation;
    }

    public void setYLocation(int yLocation) {
        this.yLocation = yLocation;
    }

    public int getNumberOfSides() {
        return numberOfSides;
    }

    public Shape(int xLocation, int yLocation, int numberOfSides) {
        this.xLocation = xLocation;
        this.yLocation = yLocation;
        this.numberOfSides = numberOfSides;
    }
}

Rectangle:

import java.awt.Color;
import java.awt.Graphics;


public class Rectangle extends Shape {

    private int width;
    private int height;

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public Rectangle(int xLocation, int yLocation, int width, int height ) {
        super(xLocation, yLocation, 4);
        this.width = width;
        this.height = height;
        this.areaInfo = "Multiply width * height";
        this.perimeterInfo = "Add the lengths of each side";
    }

    public void paint(Graphics g){
        g.setColor(Color.BLACK);        
        g.fillRect(xLocation, yLocation, width, height);
    }
}

Canvas:

public class DrawingCanvas extends JPanel implements Serializable{

    private ArrayList<Shape> shapeList;
    OptionsPanel options;

    public void addShape(Shape shape){
        shapeList.add(shape);
        this.add(shape);
        this.repaint();
    }

    public DrawingCanvas(){
        shapeList = new ArrayList<Shape>();
    }

}

Frame:

public class DrawingFrame extends JFrame implements MouseListener, MouseMotionListener {

    private OptionsPanel options;
    private DrawingCanvas canvas;
    private MenuBar menu;
    Shape s; //shape to be manipulated

    public DrawingFrame(){
        options = new OptionsPanel();
        canvas = new DrawingCanvas();
        menu = new MenuBar();

        //options.setBounds(0, 0, 100, 500);
        options.setBackground(Color.GREEN);
        canvas.setBackground(Color.yellow);
        menu.setSize(1000,200);
        menu.setBackground(Color.magenta);

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(1000,500);
        this.setTitle("Drawing Application");

        this.setLayout(new BorderLayout());
        this.getContentPane().add(options, BorderLayout.WEST);
        this.getContentPane().add(canvas, BorderLayout.CENTER);
        this.getContentPane().add(menu, BorderLayout.PAGE_START);
        this.setVisible(true);

        options.createRectangleButton.addMouseListener(this);
        options.createSquareButton.addMouseListener(this);
        options.createCircleButton.addMouseListener(this);
        options.createTriangleButton.addMouseListener(this);
        options.clearButton.addMouseListener(this);
        canvas.addMouseListener(this);
        canvas.addMouseMotionListener(this);

    }




    @Override
    public void mouseClicked(MouseEvent e) {
        boolean createShape = true;

        if(e.getSource().equals(options.createRectangleButton)){
            createShape = true;
            s = new Rectangle(50,50,400,200);
            s.addMouseListener(this);
            s.addMouseMotionListener(this); 
        }

        if (e.getSource().equals(canvas) && createShape == true){
            s.setXLocation(e.getX());
            s.setYLocation(e.getY());
            createShape = false;
            canvas.addShape(s);
        }

Absent a complete example , it's hard to say. I'd expect your DrawingCanvas to override paintComponent() in order to render the accumulated Shape instances in shapeList . You might compare your approach to that shown in GaphPanel , cited here .

图片

The code you provided is not complete, but anyway the problem is in your mouseClicked method, if you change your second if to something like the following for example:

    if (e.getSource().equals(canvas) && createShape == true){
        int x = e.getX();
        int y = e.getY();
        s = new Rectangle(x,y,x+50,y+50);
        canvas.addShape(s);
    }

then a rectangle of width & height 50 will be painted whenever you click on the canvas, depending on your x, y location (you could change the fixed width/height by using a variable based on user input). Also, I'm not sure what you're trying to do in your first if section where you're adding a MouseListener to a newly created shape that is not added to the canvas, I guess there's something else you want to do...

I had to overwrite the canvas class' paint method; call super.paint in the canvas class and repaint each shape individually

public void paint(Graphics g){
            super.paint(g);
            for(int i=0;i<shapeList.size();i++){
                ((Shape)shapeList.get(i)).paint(g);
            }
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM