不能画圆,inspite使用逻辑方式

问题描述 投票:3回答:4

我尝试使用了Java AWT绘制一个圆,我所得到的输出只是一些小的,其由多距离间隔分开,看起来并不像一个圆的全过程。代码下面给出:

class DrawFrame extends JFrame {
    int хс, yc, r, x, y;
    float p;
    DrawFrame(int rr, int c1, int c2) {
        setSize(1000, 1000);
        setTitle("circle drawing algo");
        r = rr;
        xc = c1;
        yc = c2;
    }
    public void paint(Graphics g) {
        Circl(g);
    }
    public void Circl(Graphics g) {
        x = xc - r;
        while (x <= (xc + r)) {
            for (y = yc - r; y <= (yc + r); y++) {
                p = x * x + y * y - r * r;
                if (p == 0.0)
                    g.drawOval(x, y, 2, 2);
            }
            x++;
        }
    }
java swing java-2d
4个回答
2
投票

你应该有Performing Custom PaintingPainting in AWT and Swing的读取,以获得更好的理解的绘画系统是如何工作的,以及如何你应该使用它开始。

你不应该从没有双缓冲覆盖顶层组件的paint方法外,他们实际上是复合组件。这意味着,他们有一些对他们这提供了窗口的总体功能的顶部布置额外的组件。

JRootPane and it's many layers

这意味着,有可能为你画到框架的表面东西被忽略,因为在上面的内容,它描绘了它。

你还忽略了喷漆工艺的复杂性,除非你准备接管paint方法自己的责任,你应该总是调用其super方法。

一个更好的地方,开始是一个JPanel(这是简单)并覆盖其paintComponent方法

Example

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Main {

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

    public Main() {
        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("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane(100, 100, 100));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        int xc, yc, r;

        public TestPane(int rr, int c1, int c2) {
            r = rr;
            xc = c1;
            yc = c2;
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(r * 2, r * 2);
        }

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

        public void circle(Graphics g) {
            // Credit to LAD for the algorithm updates
            int x = xc - r;
            while (x <= (xc + r)) {
                for (int y = yc - r; y <= (yc + r); y++) {
                    float p = (x - xc) * (x - xc) + (y - yc) * (y - yc) - (r * r);
                    if (p <= 0.0f)
                    {
                        g.drawOval(x, y, 2, 2);
                    }
                }
                x++;
            }


        }
    }

}

感谢法援署算法更新


1
投票

改变的第一件事就是让JFrame加入setVisible(true);给它的构造是可见的。 建议使用具有明确的含义,使代码更易读的名字。使字段范围尽可能限制,在这种情况下,让他们私人:

private int сenterX, centerY, radius; 

(X,Y和p方法变量,并且不需要是场) 避免使用magic numbers。使用常量来代替:

private static final int W = 1000, H = 1000, DOT_SIZE =2 ;

将其组合在一起,用正确的Java naming conventions和固定的算法:

import java.awt.Graphics; //add imports to make tour code mcve
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

class DrawFrame extends JFrame {

    private final int сenterX, centerY, radius;
    private static final int W = 1000, H = 1000, DOT_SIZE =2 ;

    DrawFrame(int radius, int centerX, int centerY) {
        setSize(W, H);
        setTitle("circle drawing algo");
        this.radius = radius;
        сenterX = centerX;
        this.centerY = centerY;
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//make program stop when closing frame
        setVisible(true); //make frame visible
    }

    @Override
    public void paint(Graphics g) {
       super.paint(g); 
       circl(g);
    }

    public void circl(Graphics g) {
        int x, y;
        x = сenterX - radius;
        while (x <= сenterX + radius) {
           //calculate x 
           y = (int)Math.sqrt(radius*radius - (сenterX -x)*(сenterX -x ));
           g.drawOval(x, centerY-y, 2, 2); // 2 y values for every x 
           g.drawOval(x, centerY+y, 2, 2);
           x++;
       }
    }

    // add main to make your code mcve 
    public static void main(String[] args) {
        SwingUtilities.invokeLater(()-> new DrawFrame(100, 400, 400));
    }
}

接下来的改进可能是重构所以画上一个JPanel而不是在JFrame自身完成,使用Graphics.drawOval

class DrawFrame extends JFrame {

    DrawFrame(int radius, int centerX, int centerY) {
        setTitle("circle drawing algo");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//make program stop when closing frame
        add(new DrawingPane(radius, centerX, centerY));
        pack();
        setVisible(true); //make frame visible
    }

    // add main to make your code mcve
    public static void main(String[] args) {
        SwingUtilities.invokeLater(()-> new DrawFrame(100, 400, 400));
    }
}

class DrawingPane extends JPanel{

    private final int сenterX, centerY, radius;
    private static final int W = 1000, H = 1000, DOT_SIZE =2 ;

    DrawingPane(int radius, int centerX, int centerY) {
        setPreferredSize(new Dimension(W, H));
        this.radius = radius;
        сenterX = centerX;
        this.centerY = centerY;
    }

    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawOval(сenterX, centerY, radius, radius);
    }
}

0
投票

我编辑你的代码了一下,改变了平局算法一点,以彻底划清圈。下面是重构的代码:

class DrawFrame extends JFrame {
    int xc, yc, r, x, y;
    float p;
    DrawFrame(int rr, int c1, int c2) {
        setSize(1000, 1000);
        setTitle("circle drawing algo");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Handles the window being closed
        setVisible(true); // Makes the window visible
        r = rr;
        xc = c1;
        yc = c2;
    }
    public void paint(Graphics g) {
        Graphics2D g2 = (Graphics2D)g;
        GradientPaint gp = new GradientPaint(0f,0f,Color.blue,0f,30f,Color.green); // Just sets a color for the paint
        g2.setPaint(gp);
        Circl(g2); 
    }
    public void Circl(Graphics g) {
        x = xc-r;
        while (x <= (xc+r)) {
            for (y = yc-r; y <= (yc+r); y++) {
                p = (x-xc)*(x-xc)+(y-yc)*(y-yc)-(r*r); // Edited this line so that it’s now the correct circle formula
                if (p <= 0.0f) // If the point is 0 or less, then the point is within the circle bounds
                    g.drawOval(x, y, 2, 2);
            }
            x++;
        }
    }
    public static void main(String[] args) {
        new DrawFrame(100, 500, 500);
    }
}

该代码是有点慢,不过,作为drawOval方法似乎叫了一堆的时候是相当缓慢的。所以,这个代码是主要适合于算法方面,你可以很容易地通过调用填写一个椭圆一旦执行以下操作:

g.drawOval(x, y, 200, 200);
g.fillOval(x, y, 200, 200);

0
投票

设置X为x = XC的初始值 - R,Y为Y = YC - 河并转换到笛卡尔极坐标象P = X * X + Y * Y - R *河假设,如果XC = 500,和YC = 500,R = 50,“P”永远不会为0。所以,我想你忘记当你画来计算XC,YC。我修改你的代码有点和连接的结果。

package testProject;
import java.awt.*;
import javax.swing.*;

public class DrawFrame extends JPanel {
    int xc=500, yc=500, r=150, x, y;
    int real_x, real_y;
    float p;

    public static void main(String[] args) {
        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("circle drawing algo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBackground(Color.white);
        frame.setSize(1000, 1000);
        DrawFrame panel = new DrawFrame();
        frame.add(panel);
        frame.setVisible(true);
    }



    public void paint(Graphics g) {
        Circl(g);
    }
    public void Circl(Graphics g) {
        x = -r;
        while (x <= r) {
            y = -r;
            while (y <= r) {
                p = x * x + y * y - r * r;
                // here is the change
                if (p>=0 && p<= xc) {
                    g.drawOval(x+xc, y+yc, 3, 3);
                }
                y++;
            }
            x++;
        }
    }
}

Result

© www.soinside.com 2019 - 2024. All rights reserved.