如何在没有移除先前绘制的东西的情况下重新绘制

时间:2017-01-01 10:14:31

标签: java swing graphics awt

所以,我想实现DDA算法使用带有swing的java绘制线条,但我在这里有点问题。要绘制每个像素,我使用fillRect(X,Y,1,1)。所以,我需要绘制XY的不同位置来绘制一条线。为了更新新绘制的“像素”,我使用的是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();

如何解决?

2 个答案:

答案 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