所以,我想实现DDA算法使用带有swing的java绘制线条,但我在这里有点问题。要绘制每个像素,我使用fillRect(X,Y,1,1)
。所以,我需要绘制X
和Y
的不同位置来绘制一条线。为了更新新绘制的“像素”,我使用的是revalidate()
和repaint()
,但这似乎删除了我之前绘制的像素,我只是看到了一个观点。作为一种解决方法,我在super.paintComponent(g)
中注释了paintComponent(Graphics)
,但这似乎不是一个好的解决方案,因为我无法设置背景颜色,如果我使用它减慢速度,我会看到画线Thread.sleep()
(另一方面,我只看到一个点)。这是代码
import javax.swing.*;
import java.awt.*;
public class Painter extends JPanel {
private double x1,y1,x2,y2;
Painter(int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
@Override
protected void paintComponent(Graphics g) {
//super.paintComponent(g);
setBackground(Color.black);
g.setColor(Color.RED);
g.fillRect((int)x1,(int)y1,1,1);
}
public void drawLine() {
double DX = (x2-x1);
double DY = (y2-y1);
double steps = (Math.abs(DX) > Math.abs(DY) ) ? Math.abs(DX) : Math.abs(DY);
double xIncrement = DX/(steps);
double yIncrement = DY/(steps);
try {
for (int i = 0; i < steps; ++i) {
Thread.sleep(50);
x1 += xIncrement;
y1 += yIncrement;
revalidate();
repaint();
}
}
catch (Exception e) {
}
}
}
从我的main()
我称之为
JFrame jFrame = new JFrame("Graphics");
Painter dpl = new Painter(0,0,533,333);
jFrame.add(dpl);
jFrame.setSize(720,480);
jFrame.setVisible(true);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
dpl.drawLine();
如何解决?
答案 0 :(得分:3)
我会用屏幕外图像来解决问题,这样你就不必省略super.paintComponent();
:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Painter extends JPanel {
BufferedImage offi;
Graphics offg;
private double x1,y1,x2,y2;
Painter(int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
@Override
protected synchronized void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(offi,0,0,this);
}
private void draw(){
if(offi == null){
offi = (BufferedImage)createImage(getWidth(),getHeight());
offg = offi.getGraphics();
offg.setColor(Color.black);
offg.fillRect(0,0,getWidth(),getHeight());
}
offg.setColor(Color.RED);
offg.fillRect((int)x1,(int)y1,1,1);
}
public void drawLine() {
double DX = (x2-x1);
double DY = (y2-y1);
double steps = (Math.abs(DX) > Math.abs(DY) ) ? Math.abs(DX) : Math.abs(DY);
double xIncrement = DX/(steps);
double yIncrement = DY/(steps);
for (int i = 0; i < steps; ++i) {
x1 += xIncrement;
y1 += yIncrement;
/*try{
Thread.sleep(50); //sleep if you want it to be animated
}catch(InterruptedException e){
e.printStackTrace();
}*/
draw();
repaint();
}
}
public static void main(String[] args){
SwingUtilities.invokeLater(() -> {
JFrame jFrame = new JFrame("Graphics");
Painter dpl = new Painter(0,0,533,333);
jFrame.add(dpl);
jFrame.setSize(720,480);
jFrame.setResizable(false);
jFrame.setVisible(true);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
new Thread(() -> dpl.drawLine()).start();;
});
}
}
您有时看到一条线,有时只看到一个点的原因是,swing会合并在短时间内发生的连续repaint()
次呼叫。
答案 1 :(得分:2)
您应该跟踪当前点以重绘它们。
private final List<ArrayList<Integer>> points = new ArrayList<ArrayList<Integer>>();
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.black);
g.setColor(Color.RED);
for(ArrayList<Integer> point : points) {
g.fillRect(point.get(0),point.get(1),1,1);
}
}
public void drawLine() {
double DX = (x2-x1);
double DY = (y2-y1);
double steps = (Math.abs(DX) > Math.abs(DY) ) ? Math.abs(DX) : Math.abs(DY);
double xIncrement = ((double)DX/(double)(steps));
double yIncrement = ((double)DY/(double)(steps));
try {
for (int i = 0; i < steps; ++i) {
Thread.sleep(50);
x1 += xIncrement;
y1 += yIncrement;
points.add(new ArrayList<Integer>(){{add((int)x1); add((int)y1);}});
revalidate();
repaint();
}
}
catch (Exception e) {
}
}
这是一个糟糕的设计,但我是为了展示你必须做的事情。最好的情况是创建一个Point类并将您的点存储在ArrayList
。