我尝试使用了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++;
}
}
你应该有Performing Custom Painting和Painting in AWT and Swing的读取,以获得更好的理解的绘画系统是如何工作的,以及如何你应该使用它开始。
你不应该从没有双缓冲覆盖顶层组件的paint
方法外,他们实际上是复合组件。这意味着,他们有一些对他们这提供了窗口的总体功能的顶部布置额外的组件。
这意味着,有可能为你画到框架的表面东西被忽略,因为在上面的内容,它描绘了它。
你还忽略了喷漆工艺的复杂性,除非你准备接管paint
方法自己的责任,你应该总是调用其super
方法。
一个更好的地方,开始是一个JPanel
(这是简单)并覆盖其paintComponent
方法
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++;
}
}
}
}
感谢法援署算法更新
改变的第一件事就是让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);
}
}
我编辑你的代码了一下,改变了平局算法一点,以彻底划清圈。下面是重构的代码:
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);
设置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++;
}
}
}