延迟的JPanel上绘图

延迟的JPanel上绘图

本文介绍了java在带有定时器/延迟的JPanel上绘图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作一个小的马赛克程序,它在 JPanel 上随机绘制正方形.我想这样做,它每 0.2 秒绘制 1 个正方形(不是一次全部绘制),但到目前为止,我只能使用 while 循环一次绘制全部.我曾尝试使用 ActionListener 和 Timer,但我发现我无法将相同的 Graphics g 传递给 ActionListener.然后我尝试使用 Thread.Sleep(200) 但随后应用程序冻结了.现在我已经尝试过 System.currentTimeMillis();但它和 Threads 一样......在互联网上搜索了所有但没有找到任何有效的东西.

I'm trying to make a small Mosaic programm, that draws squares randomly all over the JPanel. I want to make it so, that it draws every 0,2 sec 1 square (not all at once), but so far i can make only it to draw all at once with a while loop. I have tried with ActionListener and Timer, but i found out, that i cant pass the same Graphics g to ActionListener. Then i tried with Thread.Sleep(200) but then the app froze. Now i have tried with System.currentTimeMillis(); but its same as with Threads... Searched all over the internet but didnt find anything that works.

主要内容:

import javax.swing.JApplet;


public class Main extends JApplet{
public void init(){
    setSize(500, 300);
    Mosaic mosaic = new Mosaic();

    setContentPane(mosaic);

}
}

应用:

import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JPanel;

public class Mosaic extends JPanel{

private int width, height;
private int ruut; // square
private int w = width / 2, h = height / 2; // middle of the app

Random rand = new Random();
Color color;

public Mosaic(){
    this(500, 300, 10);
}

public Mosaic(int width, int height, int ruut){
    this.width = width;
    this.height = height;
    this.ruut = ruut;
    setBackground(Color.BLACK);
}

public void paintComponent(Graphics g){
    super.paintComponent(g);
    //draws random squares
    while (true) {
        moveNext(g);
        wait(200);
    }
}

//delay n millisec
public void wait(int n){
    long t0, t1;
    t0 = System.currentTimeMillis();

    do {
        t1 = System.currentTimeMillis();
    } while ((t1 - t0) < n);
}

//next square
public void moveNext(Graphics g){

    int r = rand.nextInt(4);

    switch (r) {
    case 1:
        h += ruut;
        wallTest();
        break;
    case 2:
        h -= ruut;
        wallTest();
        break;
    case 3:
        w -= ruut;
        wallTest();
        break;
    case 4:
        w -= ruut;
        wallTest();
        break;
    }

    color = new Color(0, rand.nextInt(255-50)+50, 0);
    g.setColor(color);
    g.fillRect(w, h, ruut, ruut);
}

public void wallTest(){
    if (h > height){
        h = 0;
    }
    if (h < 0){
        h = height;
    }
    if (w > width){
        w = 0;
    }
    if (w < 0){
        w = width;
    }
}

}

推荐答案

您需要维护一个离屏缓冲区,并在计时器事件的控制下将图块绘制到该缓冲区中.

You need to maintain an off-screen buffer, and draw tiles into that buffer under control of timer events.

然后 paintComponent 简单地将该缓冲区复制到屏幕上.

Then paintComponent simply copies that buffer to the screen.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.Random;

import javax.swing.JPanel;
import javax.swing.Timer;

public class Mosaic extends JPanel{

    private int width, height;
    private int ruut; // square
    private int w = width / 2, h = height / 2; // middle of the app
    private BufferedImage buffer;

    Random rand = new Random();
    Color color;

    public Mosaic(){
        this(500, 300, 10);
    }

    public Mosaic(int width, int height, int ruut){
        this.width = width;
        this.height = height;
        this.ruut = ruut;
        this.buffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        setBackground(Color.BLACK);
        setPreferredSize(new Dimension(width, height));
        setDoubleBuffered(false);
        new Timer(200, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                moveNext(buffer.getGraphics());
            }
        }).start();
    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawImage(buffer, 0, 0, this);
    }

    //next square
    public void moveNext(Graphics g){

        int r = rand.nextInt(4);

        switch (r) {
        case 1:
            h += ruut;
            wallTest();
            break;
        case 2:
            h -= ruut;
            wallTest();
            break;
        case 3:
            w -= ruut;
            wallTest();
            break;
        case 4:
            w -= ruut;
            wallTest();
            break;
        }

        color = new Color(0, rand.nextInt(255-50)+50, 0);
        g.setColor(color);
        g.fillRect(w, h, ruut, ruut);
        repaint();
    }

    public void wallTest(){
        if (h > height){
            h = 0;
        }
        if (h < 0){
            h = height;
        }
        if (w > width){
            w = 0;
        }
        if (w < 0){
            w = width;
        }
    }
}

这篇关于java在带有定时器/延迟的JPanel上绘图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-05 16:16