简体   繁体   中英

Java Swing Draw Applet

I'm doing an assignment and I've hit a brick wall and could really use some direction. The program launches a Java GUI applet (I have this working) and within that applet, you can select between a few options, such as, the shape type (Oval or Rectangle), Fill Type (Solid or Hollow) and Color (a few color options).

There's a single Draw button in the app and this draw button should draw an image based on the selections made above.

For shape type, I'm looking at the selection with an "if" statement and statically setting the drawing to be an oval or rectangle based on what's selected.

                for (String value : shapeType) {
                    if (value.equals("Rectangle")) {
                        shapeDimensions = new Rectangle(0, 0, 200, 200);
                    } else {
                        shapeDimensions = new Rectangle(40, 30, 100, 125);
                    }
                }

The same applies for Color, if the selection is Red then I set the "color" variable to color = new Color(255, 0, 0) .

The problem I'm having is with the Fill Type (Solid or Hollow)? I'm not sure what to do with this. I've put all of my code in below for reference. As you will see, I have a custom Shape abstract Class and constructor that I should be passing this information too. I then have methods such as setColor and getSolid along with two sub-classes called Rectangle and Oval where depending on my selection of the shape type (Oval or Rectangle), I should draw one of those shapes.

I have no idea what to do with Fill Type or how to pass that to something. I'm also not sure I'm using the correct parameter types under my Shape class. I'm also not sure I should be doing the calculations to determine the color and Shape Type the way I am under my draw button actionListener. Any and all help would be much appreciated!

package PRJ3;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;

public class PRJ3 extends JFrame {
    public PRJ3() {
    }

    abstract static class Shape extends Rectangle {
        private static Color shapeColor;
        private static Shape shape;
        private static Rectangle shapeType;

        Shape(Rectangle shapeType, Color shapeColor, Shape shapeFill) {
            Shape.shapeType = shapeType;
            Shape.shapeColor = shapeColor;
            Shape.shape = shapeFill;
        } // end Shape constructor

        public void setColor(Color shapeColor) {
            /** should accept the graphics object as a parameter and set the color for the next
             *  draw operation to the color of the current shape.
             */
            Shape.shapeColor = shapeColor;
        }

        public Shape getSolid() {
            return shape;
        }

        static int getNoOfShapes() {
            return 1;
        }

        abstract void draw (Graphics graphicObject);

        static class Oval extends Shape {
        Dimension objectDimension;
        Rectangle graphicObject;
        Color shapeColor;
        Shape shapeFill;

        Oval(Rectangle graphicObject, Color shapeColor, Shape shapeFill) {
            super(graphicObject, shapeColor, shapeFill);
        }

            @Override
            void draw(Graphics graphicObject) {

            }

        } // end over Oval subClass

        static class Rectangular extends Shape {

        Rectangular(Rectangle graphicObject, Color shapeColor, Shape shapeFill) {
            super(graphicObject, shapeColor, shapeFill);
        }

        @Override
        void draw(Graphics graphicObject) {
            Drawing drawRectangle = new Drawing();
        }

    } // end of Rectangle subClass

        static class Drawing extends JPanel {
            private Shape shape;

            @Override
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.drawString("Shapes: " + Shape.getNoOfShapes(), 10, 20);
                /** Shape isn't initialized when this is called the first time */
                if (shape != null) {
                    shape.draw(g);
                }
            }

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }

            public void drawShape() throws OutsideBounds {
                // check provided size vs preferred size
                if (shape.getWidth() > this.getPreferredSize().getWidth() || shape.getHeight() > this.getPreferredSize().getHeight()) {
                    throw new OutsideBounds();
                } else {
                    this.shape = shape;
                    repaint();
                }

            } // end drawShape

        } // end of Drawing subClass

        static class OutsideBounds extends Throwable {
}

    } // end of Shape parent class

    static public void main(String[] args) {

        JPanel contentPane;
        JTextField tfWidth;
        JTextField tfHeight;
        JTextField tfxCoordinate;
        JTextField tfyCoordinate;
        JComboBox cbxShapeType;
        JLabel lblShapeType;
        JPanel panelShapeDrawing;
        JLabel lblFillType;
        JComboBox cbxFillType;
        JLabel lblColor;
        JComboBox cbxColor;
        JLabel lblWidth;
        JLabel lblHeight;
        JLabel lblxCoordinate;
        JLabel lblyCoordinate;
        JButton btnDraw;
        final String[] shapeType = new String[1];
        final String[] shapeColor = new String[1];
        final String[] shapeFill = new String[1];

        JFrame Frame = new JFrame("Geometric Drawing");
        Frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Frame.setBounds(100, 100, 601, 330);
        contentPane = new JPanel();
        Frame.setContentPane(contentPane);
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        GridBagLayout gbl_contentPane = new GridBagLayout();
        gbl_contentPane.columnWidths = new int[] {20, 106, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0};
        gbl_contentPane.rowHeights = new int[] {30, 30, 30, 30, 29, 30, 29, 30, 19, 30, 0};
        gbl_contentPane.columnWeights = new double[]{0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, Double.MIN_VALUE};
        gbl_contentPane.rowWeights = new double[]{0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
        contentPane.setLayout(gbl_contentPane);

        lblShapeType = new JLabel("Shape Type");
        GridBagConstraints gbc_lblShapeType = new GridBagConstraints();
        gbc_lblShapeType.fill = GridBagConstraints.HORIZONTAL;
        gbc_lblShapeType.insets = new Insets(0, 0, 5, 5);
        gbc_lblShapeType.gridx = 1;
        gbc_lblShapeType.gridy = 1;
        contentPane.add(lblShapeType, gbc_lblShapeType);

        String[] shapeTypes = {"" ,"Oval", "Rectangle"};
        cbxShapeType = new JComboBox(shapeTypes);
        GridBagConstraints gbc_cbxShapeType = new GridBagConstraints();
        gbc_cbxShapeType.fill = GridBagConstraints.HORIZONTAL;
        gbc_cbxShapeType.insets = new Insets(0, 0, 5, 5);
        gbc_cbxShapeType.gridx = 2;
        gbc_cbxShapeType.gridy = 1;
        contentPane.add(cbxShapeType, gbc_cbxShapeType);

        panelShapeDrawing = new JPanel();
        panelShapeDrawing.setLayout(new BorderLayout());
        String title = "Shape Drawing";
        Border border = BorderFactory.createTitledBorder(title);
        panelShapeDrawing.setBorder(border);
        GridBagConstraints gbc_panelShapeDrawing = new GridBagConstraints();
        gbc_panelShapeDrawing.insets = new Insets(0, 0, 5, 0);
        gbc_panelShapeDrawing.gridwidth = 10;
        gbc_panelShapeDrawing.gridheight = 8;
        gbc_panelShapeDrawing.fill = GridBagConstraints.BOTH;
        gbc_panelShapeDrawing.gridx = 3;
        gbc_panelShapeDrawing.gridy = 1;
        contentPane.add(panelShapeDrawing, gbc_panelShapeDrawing);

        lblFillType = new JLabel("Fill Type");
        GridBagConstraints gbc_lblFillType = new GridBagConstraints();
        gbc_lblFillType.fill = GridBagConstraints.HORIZONTAL;
        gbc_lblFillType.insets = new Insets(0, 0, 5, 5);
        gbc_lblFillType.gridx = 1;
        gbc_lblFillType.gridy = 2;
        contentPane.add(lblFillType, gbc_lblFillType);

        String[] fillTypes = {"", "Solid", "Hollow"};
        cbxFillType = new JComboBox(fillTypes);
        GridBagConstraints gbc_cbxFillType = new GridBagConstraints();
        gbc_cbxFillType.insets = new Insets(0, 0, 5, 5);
        gbc_cbxFillType.fill = GridBagConstraints.BOTH;
        gbc_cbxFillType.gridx = 2;
        gbc_cbxFillType.gridy = 2;
        contentPane.add(cbxFillType, gbc_cbxFillType);

        lblColor = new JLabel("Color");
        GridBagConstraints gbc_lblColor = new GridBagConstraints();
        gbc_lblColor.fill = GridBagConstraints.HORIZONTAL;
        gbc_lblColor.insets = new Insets(0, 0, 5, 5);
        gbc_lblColor.gridx = 1;
        gbc_lblColor.gridy = 3;
        contentPane.add(lblColor, gbc_lblColor);

        String[] supportedColors = {"", "Red", "Black", "Orange", "Yellow", "Green", "Blue", "Magenta"};
        cbxColor = new JComboBox(supportedColors);
        GridBagConstraints gbc_cbxColor = new GridBagConstraints();
        gbc_cbxColor.insets = new Insets(0, 0, 5, 5);
        gbc_cbxColor.fill = GridBagConstraints.HORIZONTAL;
        gbc_cbxColor.gridx = 2;
        gbc_cbxColor.gridy = 3;
        contentPane.add(cbxColor, gbc_cbxColor);

        lblWidth = new JLabel("Width");
        GridBagConstraints gbc_lblWidth = new GridBagConstraints();
        gbc_lblWidth.fill = GridBagConstraints.HORIZONTAL;
        gbc_lblWidth.insets = new Insets(0, 0, 5, 5);
        gbc_lblWidth.gridx = 1;
        gbc_lblWidth.gridy = 4;
        contentPane.add(lblWidth, gbc_lblWidth);

        tfWidth = new JTextField();
        GridBagConstraints gbc_tfWidth = new GridBagConstraints();
        gbc_tfWidth.fill = GridBagConstraints.BOTH;
        gbc_tfWidth.insets = new Insets(0, 0, 5, 5);
        gbc_tfWidth.gridx = 2;
        gbc_tfWidth.gridy = 4;
        contentPane.add(tfWidth, gbc_tfWidth);
        tfWidth.setColumns(10);

        lblHeight = new JLabel("Height");
        GridBagConstraints gbc_lblHeight = new GridBagConstraints();
        gbc_lblHeight.fill = GridBagConstraints.HORIZONTAL;
        gbc_lblHeight.insets = new Insets(0, 0, 5, 5);
        gbc_lblHeight.gridx = 1;
        gbc_lblHeight.gridy = 5;
        contentPane.add(lblHeight, gbc_lblHeight);

        tfHeight = new JTextField();
        tfHeight.setColumns(10);
        GridBagConstraints gbc_tfHeight = new GridBagConstraints();
        gbc_tfHeight.insets = new Insets(0, 0, 5, 5);
        gbc_tfHeight.fill = GridBagConstraints.BOTH;
        gbc_tfHeight.gridx = 2;
        gbc_tfHeight.gridy = 5;
        contentPane.add(tfHeight, gbc_tfHeight);

        lblxCoordinate = new JLabel("x coordinate");
        GridBagConstraints gbc_lblxCoordinate = new GridBagConstraints();
        gbc_lblxCoordinate.fill = GridBagConstraints.HORIZONTAL;
        gbc_lblxCoordinate.insets = new Insets(0, 0, 5, 5);
        gbc_lblxCoordinate.gridx = 1;
        gbc_lblxCoordinate.gridy = 6;
        contentPane.add(lblxCoordinate, gbc_lblxCoordinate);

        tfxCoordinate = new JTextField();
        tfxCoordinate.setColumns(10);
        GridBagConstraints gbc_tfxCoordinate = new GridBagConstraints();
        gbc_tfxCoordinate.insets = new Insets(0, 0, 5, 5);
        gbc_tfxCoordinate.fill = GridBagConstraints.BOTH;
        gbc_tfxCoordinate.gridx = 2;
        gbc_tfxCoordinate.gridy = 6;
        contentPane.add(tfxCoordinate, gbc_tfxCoordinate);

        lblyCoordinate = new JLabel("y coordinate");
        GridBagConstraints gbc_lblyCoordinate = new GridBagConstraints();
        gbc_lblyCoordinate.fill = GridBagConstraints.HORIZONTAL;
        gbc_lblyCoordinate.insets = new Insets(0, 0, 5, 5);
        gbc_lblyCoordinate.gridx = 1;
        gbc_lblyCoordinate.gridy = 7;
        contentPane.add(lblyCoordinate, gbc_lblyCoordinate);

        tfyCoordinate = new JTextField();
        tfyCoordinate.setColumns(10);
        GridBagConstraints gbc_tfyCoordinate = new GridBagConstraints();
        gbc_tfyCoordinate.insets = new Insets(0, 0, 5, 5);
        gbc_tfyCoordinate.fill = GridBagConstraints.BOTH;
        gbc_tfyCoordinate.gridx = 2;
        gbc_tfyCoordinate.gridy = 7;
        contentPane.add(tfyCoordinate, gbc_tfyCoordinate);

        btnDraw = new JButton("Draw");
        GridBagConstraints gbc_btnDraw = new GridBagConstraints();
        gbc_btnDraw.anchor = GridBagConstraints.EAST;
        gbc_btnDraw.fill = GridBagConstraints.VERTICAL;
        gbc_btnDraw.insets = new Insets(0, 0, 5, 5);
        gbc_btnDraw.gridx = 2;
        gbc_btnDraw.gridy = 8;
        contentPane.add(btnDraw, gbc_btnDraw);

        btnDraw.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                Shape.Drawing customShape = new Shape.Drawing();
                shapeType[0] = (String) cbxShapeType.getSelectedItem();
                shapeFill[0] = (String) cbxFillType.getSelectedItem();
                shapeColor[0] = (String) cbxColor.getSelectedItem();
                Rectangle shapeDimensions = null;
                Color color = null;
                Shape shape = null;


                for (String value : shapeType) {
                    if (value.equals("Rectangle")) {
                        shapeDimensions = new Rectangle(0, 0, 200, 200);
                    } else {
                        shapeDimensions = new Rectangle(40, 30, 100, 125);
                    }
                }

                for (String value : shapeFill) {
                    if (value.equals("Fill")) {
                        Shape fill = new Rectangle2D()
                    }
                }

                for (String s : shapeColor) {
                    if (s.equals("Red")) {
                        color = new Color(255, 0, 0);
                    } else if (s == "Black") {
                        color = new Color(0, 0, 0);
                    } else if (s == "Orange") {
                        color = new Color(255, 102, 0);
                    } else if (s == "Yellow") {
                        color = new Color(255, 255, 0);
                    } else if (s == "Green") {
                        color = new Color(0, 204, 0);
                    } else if (s == "Blue") {
                        color = new Color(0, 0, 255);
                    } else if (s == "Magenta") {
                        color = new Color(255, 0, 255);
                    }
                }

                Color finalColor = color;
                Shape test = new Shape(shapeDimensions, finalColor, shape) {
                    @Override
                    void draw(Graphics graphicObject) {
                    }
                };
                test.setColor(color);
            }
        });

        panelShapeDrawing.setVisible(true);
        contentPane.setVisible(true);
        Frame.setVisible(true);

    } // end main

} // end PRJ3

Also, the classes and methods you see here are the ones that we were advised to use,

Well, I don't know what has been given to you and what you have written yourself, but what I see above is confusing.

To me it looks like you have 3 properties to control the painting:

  1. Rectangle, which contains the location and size of the shape to be painted.
  2. Color
  3. Filled, which should be a Boolean property to control if the shaped should be painted filled or with an outline only.

So your Shape class should not extend Rectangle. It should just be a class with the above 3 properties and your draw(Graphics g) method.

Note the JDK has a Shape class so I don't like to use the same name as it causes confusion.

So I would do something like:

public abstract class DrawableShape
{
    protected Rectangle rectangle;
    protected Color color;
    protected boolean filled;

    public DrawableShape(Rectangle rectangle, Color color, boolean filled)
    {
        this.rectangle = rectangle;
        this.color = color;
        this.filled = filled;
    }

    abstract void draw(Graphics g);
}

Now you need to implement the painting code for your Rectangle and Oval objects. Something like:

public class DrawableRectangle extends DrawableShape
{
    @Override
    public void draw(Graphics g)
    {
        g.setColor( color );

        if (filled)
            g.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
        else
            g.drawRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
    }
}

Now in your DrawingPanel you need a method like:

public void setDrawableShape(DrawableShape drawableShape)
{
    this.drawableShape = drawableShape;
    repaint();
}

Ant the painting code need to paint this shape:

@Override
protected void paintComponent(Graphics g)
{
    super.paintComponent( g );
    drawableShape.draw();
}

Then in the ActionListener you code you need to add the DrawableShape to your Drawing class:

DrawableShape drawableShape = null;

if (value.equals("Rectangle"))
    drawableShape = new DrawableRectangle(….);
else
    drawableShape = new DrawableOval(...);

drawing.setDrawableShape( drawableShape );

The above structure will allow you to paint only a single shape on your Drawing panel. If you need multiple shapes, then you need to modify your Drawing class. The link I provided you above on "Custom Painting Approaches" shows how to do this.

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