1. 程式人生 > >Java 把畫圖和投屏分開 不用雙緩衝解決螢幕閃爍問題

Java 把畫圖和投屏分開 不用雙緩衝解決螢幕閃爍問題

投屏模組——MyCanvas類

運用裡面的getImageAndPrintIt(BufferedImage bufferedImage)方法實現投屏,bufferedImage是提前畫好的圖片。

也就是說,只讓Canvas實現投屏功能,把畫圖功能分離出去。

package madokast;

import java.awt.*;
import java.awt.image.BufferedImage;

public class MyCanvas extends Canvas {
    //用於接收外來圖片(已經在外面畫好了)
    private BufferedImage ImageToBePaint;

    //對外的介面,用於得到外界的圖片,在此中呼叫repaint()方法
    public void getImageAndPrintIt(BufferedImage bufferedImage)
    {
        //拿到要畫的圖片
        this.ImageToBePaint = bufferedImage;
        //畫圖順序:repaint()->update()->paint()
        super.repaint();
    }

    @Override
    //重寫update方法,該方法原本用於清屏+呼叫paint()

    //這個方法中的Graphics g的和paint(Graphics g)方法中的g,都是直接指向螢幕的畫筆
    //原本update()方法帶有清屏功能,即g.clearRect(),用背景色重置螢幕
    //在我的MyCanvas類中,這東西沒必要,直接用下一張圖片覆蓋上一張即可,沒必要清屏
    //以前需要清屏是因為以前的畫圖寫在了重寫的paint()方法中,這個方法裡我們只管畫圖,不管清屏

    //重寫update(),覆蓋【清屏+呼叫paint()】的功能(等於paint不再被呼叫了————實際上還以被呼叫了一次...大概是初始化的時候)
    //直接用這裡的 g 繪製從getImageAndPrintIt(BufferedImage bufferedImage)得到的圖片
    public void update(Graphics g) {g.drawImage(ImageToBePaint,0,0,null); }

    //paint(Graphics g)還是被呼叫了一次...不知道為什麼
    //@Override
    //public void paint(Graphics g) {
    //    super.paint(g);
    //    int x=1/0;
    //}

    @Override
    @Deprecated
    //最後。不要用repaint(),應該使用getImageAndPrintIt(BufferedImage bufferedImage)
    public void repaint() { super.repaint(); }
}

畫圖模組——一段main函式的小測試

package madokast;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;

public class CanvasRelearnMain {
    private static int x=0;

    public static void main(String[] args) {
        final int ImageWidth = 800;
        final int ImageHeight = 600;

        Frame frame = new Frame("測試");
        MyCanvas myCanvas = new MyCanvas();
        myCanvas.setBounds(0,0,ImageWidth,ImageHeight);
        frame.add(myCanvas,BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);


        BufferedImage bufferedImage = new BufferedImage(ImageWidth,ImageHeight, BufferedImage.TYPE_INT_RGB);
        Graphics pen = bufferedImage.createGraphics();
        Color blue = new Color(0x0000FF);
        Color red = new Color(0xFF0000);

        Timer timer = new Timer(10,t->{
            //清屏
            pen.setColor(blue);
            pen.fillRect(0,0,ImageWidth,ImageHeight);

            //畫圖
            pen.setColor(red);
            pen.fillRect(x++,200,30,30);

            //投屏
            myCanvas.getImageAndPrintIt(bufferedImage);
        });

        timer.start();
    }
}