根据Java中的用户输入绘制一个圆

时间:2014-09-21 06:23:29

标签: java swing paintcomponent joptionpane

我一遍又一遍地试图找到解决这个问题的方法,但我似乎无法理解如何解决它。

我正在尝试编写一个简单的程序,在程序中绘制一个带有这些规范的圆圈:

  1. 使用输入框(JOptionPane)询问用户圆的半径。
  2. 在输入框(JOptionPane)中询问用户圆圈的x和y坐标。
  3. 计算圆的周长。
  4. 计算圆的面积。
  5. 在圆形图下方显示区域和周长。
  6. 不知何故,它不会绘制圆圈,并计算圆周和面积。能帮我找到解决这个问题的方法吗?

    以下是我的代码:

    -------主要-------

    package circleSquarePackage;
    
    import circleSquarePackage.Circle;
    
    import javax.swing.JOptionPane;
    import javax.swing.JFrame;
    
    public class CircleTester {
    
        public static void main(String[] args) 
            {
    
            JFrame frame = new JFrame();
    
            // Display Circle in the frame
            frame.setSize(600, 500);
            frame.setTitle("CircleSquare");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            // Create Circle Components
            Circle round = new Circle();
            frame.add(round);
    
            frame.setVisible(true);
    
        }
    
    }
    

    --------其他类---------

    package circleSquarePackage;
    
    import javax.swing.JComponent;
    import java.awt.geom.Ellipse2D;
    import java.awt.geom.Ellipse2D.Double;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Color;
    
    import javax.swing.JOptionPane;
    
    
    public class Circle extends JComponent {
        // Member instance field
        private Ellipse2D.Double sphere;
        private int radius;
        double circumference, area;
    
        String x1; // starting x co-ordinate
        String y1; // starting y co-ordinate
        String r1; // radius for circle
        String draw;
    
        int x = 0;
        int y = 0;
        int r = 0;
    
    
        // Default constructor
        public Circle()
        {
            sphere = new Ellipse2D.Double();
        }
    
        // User defined constructor
        public Circle(int xAxis, int yAxis, int rad)
        {
            rad = r;
            xAxis = x;
            yAxis = y;
            sphere = new Ellipse2D.Double(xAxis, yAxis, rad, rad);
        }
    
        // Accessor methods
        public double calcCircumference()
        {
        return circumference = 2 * Math.PI * radius;
        }
    
        public double calcArea()
        {
            return area = Math.PI * radius * radius;
        }
    
        // Methods
        public void inputX()
        {
            x1 = JOptionPane.showInputDialog(null, "Input center (x value): ");
            x = Integer.parseInt(x1);
        }
    
        public void inputY()
        {
            y1 = JOptionPane.showInputDialog(null, "Input center (y value): ");
            y = Integer.parseInt(y1);
    
        }
    
        public void inputRadius()
        {
            r1 = JOptionPane.showInputDialog(null, "Input radius: ");
            r = Integer.parseInt(r1);
        }
    
        public void paintComponent(Graphics g)
        {
            // Cast 1D to 2D graphics
            Graphics2D g2 = (Graphics2D) g;
    
            g2.setColor(Color.BLUE); // set circle color to blue
            g2.fill(sphere);
            g2.draw(sphere);
    
            g2.setColor(Color.BLUE);
            g2.drawString("Circumference = " + calcCircumference(), 5, 450);
            g2.drawString("Area = " + calcCircumference(), 200, 450);
        }
    }
    

    基于PEESKILLET答案的更新

    圈子类

    package circleSquarePackage;
    
    import javax.swing.JComponent;
    import java.awt.geom.Ellipse2D;
    import java.awt.geom.Ellipse2D.Double;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Color;
    import java.awt.Dimension;
    
    import javax.swing.JOptionPane;
    
    
    public class Circle extends JComponent {
        // Member instance field
        private Ellipse2D.Double sphere;
        private int radius;
        double circumference, area;
    
    
        // Default constructor
        public Circle()
        {
            sphere = new Ellipse2D.Double();
        }
    
        public void setSphere(Ellipse2D.Double sphere) {
            this.sphere = sphere;
            repaint();
        }
    
        // User defined constructor
        public Circle(int xAxis, int yAxis, int rad)
        {
            sphere = new Ellipse2D.Double(xAxis, yAxis, rad, rad);
        }
    
        // Accessor methods
        public double calcCircumference()
        {
        return circumference = 2 * Math.PI * radius;
        }
    
        public double calcArea()
        {
            return area = Math.PI * radius * radius;
        }
    
        // Methods
        public void inputX()
        {
            int x = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter x"));
            double y = sphere.y; // why is there a double y here when it asks for x?
            Ellipse2D.Double newSphere = new Ellipse2D.Double(x, y, size, size);
            setSphere(newSphere);
        }
    
        public void inputY()
        {
            int y = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter y"));
            double x = sphere.x; 
            Ellipse2D.Double newSphere = new Ellipse2D.Double(x, y, size, size);
            setSphere(newSphere);
        }
    
        public void inputRadius() 
        {
            // is this how I do for radius?
            int r = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter radius"));
            int size = r * 2;
            Ellipse2D.Double newSphere = new Ellipse2D.Double(x, y, size, size);
            setSphere(newSphere);
        }
    
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;
    
            g2.setColor(Color.BLUE); // set circle color to blue
            g2.fill(sphere);
            g2.draw(sphere);
    
            g2.drawString("Circumference: " + calcCircumference(), 5, 490);
    
        }
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(600, 500);
        }
    }
    

    -------- CircleTester类--------

    package circleSquarePackage;
    
    import circleSquarePackage.Circle;
    
    import javax.swing.JOptionPane;
    import javax.swing.JFrame;
    import javax.swing.SwingUtilities;
    import java.awt.geom.Ellipse2D;
    import java.awt.geom.Ellipse2D.Double;
    
    public class CircleTester {
        /*
        private static Ellipse2D.Double getCircle() {
            int x = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter integer for x-coordinates:"));
            int y = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter integer for y-coordinates:"));
            int radius = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter radius of circle:"));
            int size = radius * 2;
            return new Ellipse2D.Double(x, y, size, size);
        }*/
    
        public static void main(String[] args) 
        {
            // Is there a way to call the inputX(), inputY(), and inputRadius() here?
    
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    JFrame frame = new JFrame();
    
    
                    frame.setTitle("CircleSquare");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
                    Circle round = new Circle();
                    frame.add(round);
    
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
    
                    /*
                    Ellipse2D.Double newCircle = getCircle();
                    round.setSphere(newCircle);
                    */
                }
            });
    
        }
    
    }
    

2 个答案:

答案 0 :(得分:5)

在no-arg Circle构造函数中,您在获取值之前创建了sphere(默认Ellipse2D.Double)。您应该在这些值上创建基于sphere ,就像您在三个arg构造函数中一样

来自Ellipse2D.Double

  

Ellipse2D.Double()   
构造一个新的Ellipse2D,初始化为位置(0,0)和大小(0,0)。

另一种设计可能性

  1. setSphere班级中设置Circle方法,您可以设置椭圆并重新绘制

    public void setSphere(Ellepse2D.Double sphere) {
        this.sphere = sphere;
        repaint();
    }
    
  2. 在显示框架后仍然显示所有JOptionPane。看起来是对的。然后,当您获得值时,可以使用新的setSphereCircle课程上致电Ellipse2D.Double,它将显示在面板中。

  3. 其他说明:

    • 进行自定义绘画时,最好覆盖绘制的组件上的getPreferredSize(),然后只需在框架上调用pack(),而不是setSize()

    • 请参阅初始主题。 Swing应用程序应该在Event Dispatch Thread上发布。

    • 此外,x, y, etc类中不需要冗余的Circle值。它们已被Ellipse对象占据。如果您需要获取某些值,请从中获取,即sphere.xsphere.y.

    这是我上面提到的建议的重构。 (您还需要进行一些检查以确保数字实际上是类型。我很懒惰)

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.geom.Ellipse2D;
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    import javax.swing.SwingUtilities;
    
    public class CircleTester {
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    JFrame frame = new JFrame();
    
                    frame.setTitle("CircleSquare");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
                    Circle round = new Circle();
                    frame.add(round);
    
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
    
                    Ellipse2D.Double newCircle = getCircle();
                    round.setSphere(newCircle);
                }
            });
    
        }
    
        private static Ellipse2D.Double getCircle() {
            int x = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter x"));
            int y = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter x"));
            int radius = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter x"));
            int size = radius * 2;
            return new Ellipse2D.Double(x, y, size, size);
        }
    }
    
    class Circle extends JComponent {
    
        private Ellipse2D.Double sphere;
    
        public Circle() {
            sphere = new Ellipse2D.Double();
        }
    
        public void setSphere(Ellipse2D.Double sphere) {
            this.sphere = sphere;
            repaint();
        }
    
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;
    
            g2.setColor(Color.BLUE); // set circle color to blue
            g2.fill(sphere);
            g2.draw(sphere);
    
        }
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 300);
        }
    }
    

    <强>更新

      

    我想知道如何在公共void inputX(),public void inputY()和public void inputRadius()下的Circle类中放置JOptionPane请求用户输入,然后在CircleTester中调用main中的那些类?

    你可以做的就是在每个方法中调用JOPtionPane。假设你想获得x,然后调用JOptionPane,并根据该值,使用旧值并使用新x从旧椭圆创建一个新的Ellipse。然后拨打setSphere。像

    这样的东西
    public void inputX() {
        int x = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter x"));
        double y = sphere.y;
        double height = sphere.height;
        double width = sphere.width;
        Ellips2D.Double newSpehere = new Ellipse2D.Double(x, y, width, height);
        setSphere(newSphere);
    }
    

    你也可以这样做。这样,当您调用方法时,一旦输入,它将只更改一个变量。

    您还可以使用一种方法来获取所有变量,就像我在我的示例中所做的那样。

答案 1 :(得分:3)

  1. 从Circle类中获取所有UI,这意味着删除所有这些JOptionPane调用。
  2. 而是所有用户交互都应该在您的CircleTester类中。
  3. Circle类应该不关注用户IO,而只关注绘制由其属性定义的Circle。
  4. 为Circle类提供一个带有意义参数的构造函数。
  5. 在我看来,不需要Ellipse2D,因为你可以通过调用g.drawOval(....)`简单地用Graphics对象绘制你的圆圈,从而简化你的程序。
  6. 在CircleTester中获取输入参数后,创建Circle对象,传递从CircleTest获取的参数,并显示您的Circle。
  7. 另外,不要忘记在paintComponent方法覆盖中调用super.paintComponent(g)方法。
  8. 轻微的挑剔,但我不会声明周长和面积变量,而是给你的Circle类getCircumference()getArea()方法,这些方法可以在需要时当场计算这些变量。否则,如果你给Circle一个setRadius(...)方法,你必须记住改变setter方法中的其他字段,如果你将radius或其他字段公开,那么所有的方法都可以解除。玩安全,只有这两个属性的访问方法,而不是字段。