使用 Java swing GUI 的形状计算器

Shape calculator using Java swing GUI

我创建了一个不是 GUI 的形状计算器,它可以根据所选形状很好地计算面积和体积,我正在尝试为同一程序创建一个 GUI 我 运行 遇到问题时它涉及根据用户输入显示形状和结果。我有 GUI 的布局,但使用 ActionPerformed 我无法弄清楚如何获取输入并调用形状 class 来进行计算而不是显示结果。

我已经修复了我的一些错误,并将其添加到 运行 但是它给出了输入数字值的错误消息并且无法计算 0.0 以外的区域。

import javax.swing.*;
import java.awt.*;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.JRadioButton;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;


public class ControlPane extends JPanel implements ActionListener{


    // create buttons
    private JRadioButton circle;
    private JRadioButton square;
    private JRadioButton rectangle;
    private JRadioButton triangle;
    private JRadioButton sphere;
    private JRadioButton cube;
    private JRadioButton cylinder;
    private JRadioButton cone;
    private JRadioButton torus;
    private DrawPane drawPane;

    public ControlPane() {


        ButtonGroup bg1 = new ButtonGroup();
        circle = new JRadioButton("Circle");
        square = new JRadioButton("Square");
        rectangle = new JRadioButton("Rectangle");
        triangle = new JRadioButton("Triangle");

        sphere = new JRadioButton("Sphere");
        cube = new JRadioButton("Cube");
        cylinder = new JRadioButton("Cylinder");
        cone = new JRadioButton("Cone");
        torus = new JRadioButton("Torus");

        bg1.add(circle);
        bg1.add(square);
        bg1.add(rectangle);
        bg1.add(triangle);

        bg1.add(sphere);
        bg1.add(cube);
        bg1.add(cylinder);
        bg1.add(cone);
        bg1.add(torus);

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbc.weightx = 1;

        JPanel shape = new JPanel();
        shape.add(circle);
        shape.add(square);
        shape.add(rectangle);
        shape.add(triangle);
        shape.add(sphere);
        shape.add(cube);
        shape.add(cylinder);
        shape.add(cone);
        shape.add(torus);

        add(shape, gbc);

        JPanel dimension = new JPanel();
        JLabel heightLbl = new JLabel("Height: ");
        JLabel widthLbl = new JLabel("Width: ");
        JLabel sideLbl = new JLabel("Side: ");
        JLabel radius1Lbl = new JLabel("Radius 1: ");
        JLabel radius2Lbl = new JLabel("Radius 2: ");
        JTextField heightTF = new JTextField(10);
        JTextField widthTF = new JTextField(10);
        JTextField sideTF = new JTextField(10);
        JTextField radius1TF = new JTextField(10);
        JTextField radius2TF = new JTextField(10);
        heightLbl.setLabelFor(heightTF);
        widthLbl.setLabelFor(widthTF); 
        sideLbl.setLabelFor(sideTF);
        radius1Lbl.setLabelFor(radius1TF);
        radius2Lbl.setLabelFor(radius2TF);

        dimension.add(heightLbl);
        dimension.add(heightTF);
        dimension.add(widthLbl);
        dimension.add(widthTF);
        dimension.add(sideLbl);
        dimension.add(sideTF);
        dimension.add(radius1Lbl);
        dimension.add(radius1TF);
        dimension.add(radius2Lbl);
        dimension.add(radius2TF);

        add(dimension, gbc);  

        gbc.gridwidth = GridBagConstraints.REMAINDER;

        drawPane = new DrawPane();

        gbc.weightx = 1;
        gbc.weighty = 1;
        gbc.fill = gbc.BOTH;      

        JPanel draw = new JPanel();
        JLabel areaLbl = new JLabel("Area: ");
        JTextField areaTF = new JTextField(10);
        areaTF.setEditable(false);
        JLabel volumeLbl = new JLabel("Volume: ");
        JTextField volumeTF = new JTextField(10);
        volumeTF.setEditable(false); 
        JButton paint = new JButton("Draw & Calculate");

        draw.add(paint);
        draw.add(drawPane);
        draw.add(areaLbl);
        draw.add(areaTF);
        draw.add(volumeLbl);
        draw.add(volumeTF); 
        add(draw, gbc);

            paint.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                double height = 0;
                double width = 0;
                double side = 0;
                double radius1 = 0;
                double radius2 = 0;
                double area, volume;
                try {
                height = Double.parseDouble(heightTF.getText());
                width = Double.parseDouble(widthTF.getText());
                side = Double.parseDouble(sideTF.getText());
                radius1 = Double.parseDouble(radius1TF.getText());
                radius2 = Double.parseDouble(radius2TF.getText());
                } catch(NumberFormatException ex) {
                    JOptionPane.showMessageDialog(draw, "Please enter a number value.");
                }

                if (circle.isSelected()) {
                    drawPane.setDrawableShape(DrawableShape.CIRCLE);
                    area = 3.14 * radius1 * radius1;
                    areaTF.setText(" "+ area);
                } 
                else if (square.isSelected()) {
                    drawPane.setDrawableShape(DrawableShape.SQUARE);
                    area = side * side;
                    areaTF.setText(" " + area);
                }
                else if (triangle.isSelected()) {
                    drawPane.setDrawableShape(DrawableShape.TRIANGLE);
                    area = 0.5 * width * height;
                    areaTF.setText(" " + area);
                }
                else if (rectangle.isSelected()) {
                     drawPane.setDrawableShape(DrawableShape.RECTANGLE);
                    area = height * width;
                    areaTF.setText(" " + area);
                }
                else if (sphere.isSelected()) {

                    volume = (4 / 3) * 3.14 * radius1 * radius1 * radius1;
                    volumeTF.setText(" " + volume);
                }
                else if (cube.isSelected()) {

                    volume = (side * side * side);
                    volumeTF.setText(" " + volume);
                }
                else if (cylinder.isSelected()) {

                    volume = (3.14 * radius1 * radius1 * height);
                    volumeTF.setText(" " + volume);
                } 
                else if (cone.isSelected()) {
                    volume = (3.14 * radius1 * radius1 * height) / 3;
                    volumeTF.setText(" " + volume);
                }
                else if (torus.isSelected()) {
                    volume = 2 * 3.14 * 3.14 * radius1 * radius1 * radius2;
                    volumeTF.setText(" " + volume);
                }
            }
        });

      }

} 

DrawStuff class

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class DrawStuff extends JFrame {

    public static void main(String[] args) {
        new DrawStuff();
    }

    public DrawStuff() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                     UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException |     IllegalAccessException | UnsupportedLookAndFeelException ex) {
                ex.printStackTrace();
            }

            JFrame frame = new JFrame("Shape Calculator");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new ControlPane());
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    });
}
}

绘图面板class

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class DrawPane extends JPanel {

    private DrawableShape drawableShape;

    public DrawPane() {
    }

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

    public DrawableShape getDrawableShape() {
        return drawableShape;
    }

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

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
        DrawableShape shape = getDrawableShape();
        if (shape != null) {
            int width = getWidth() - 20;
            int height = getHeight() - 20;
            int size = Math.min(width, height);

            int x = (getWidth() - size) / 2;
            int y = (getHeight() - size) / 2;
            if (shape == DrawableShape.CIRCLE) {
                g2d.fillOval(x, y, size, size);
            } else if (shape == DrawableShape.SQUARE) {
                g2d.fillRect(x, y, size, size);
            } else if (shape == DrawableShape.TRIANGLE) {
                g2d.fillPolygon(new int[] {20, 40, 60}, new int[] {100, 50, 100}, 3);
            }
        }
        g2d.dispose();
    }

}

DrawableShape class

public enum DrawableShape {
    CIRCLE,
    SQUARE,
    TRIANGLE
}

为避免错误消息,您只需解析相关的 TextField,而不是全部。
例如,不需要为圆解析 heightTF 并且会抛出异常。
您可以通过将按钮动作侦听器更改为 paint.addActionListener(e -> calculate()); 来实现,其中计算定义如下:

//for simplicity only 3 shapes are handled:
private void calculate(){

    double area = 0, volume = 0;
    try {

        if (circle.isSelected()) {
            drawPane.setDrawableShape(DrawableShape.CIRCLE);
            double radius1 = Double.parseDouble(radius1TF.getText());
            area = 3.14 * radius1 * radius1;
        }
        else if (cube.isSelected()) {
            drawPane.setDrawableShape(null);
            double side = Double.parseDouble(sideTF.getText());
            volume = side * side * side;
        }
        else if (rectangle.isSelected()) {
            drawPane.setDrawableShape(DrawableShape.RECTANGLE);
            double height = Double.parseDouble(heightTF.getText());
            double width = Double.parseDouble(widthTF.getText());
            area = height * width;
        }

        areaTF.setText(" "+ area);
        volumeTF.setText(" " + volume);

    } catch(NumberFormatException ex) {
        JOptionPane.showMessageDialog(null, "Please enter a number value.");
    }
}

您需要将所有 TextField 个变量设为 class 个变量:

private final JTextField heightTF, widthTF, sideTF, radius1TF, areaTF, volumeTF;

为了更好更面向对象的解决方案定义 Shape :

interface Shape {
    double getArea();
    double getVolume();
    void draw(Graphics g, int x, int y);
}

并为每个形状实施它。例如:

class Circle implements Shape{

    private final int radius;
    Circle(int radius) {
        this.radius = radius;
    }

    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }

    @Override
    public double getVolume() {
        return 0;
    }

    @Override
    public void draw(Graphics g, int x, int y) {
        g.fillOval(x, y, radius, radius);
    }
}