Изображение мерцает при перерисовке()

Я нашел решение для моего предыдущего вопроса, который привел меня к новой проблеме.

В следующем коде я перемещаю изображение вокруг JFrame с помощью клавиш со стрелками. но каждый раз, когда я нажимаю клавишу со стрелкой, изображение кажется мерцающим, что весьма заметно, когда клавиша нажата непрерывно.

import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;


public class TestProgram extends JFrame implements KeyListener {
    private BufferedImage TestImage;
    private int cordX = 100;
    private int cordY = 100;

    public TestProgram() {
        setTitle("Testing....");
        setSize(500, 500);
        imageLoader();
        setVisible(true);
    }

    public void imageLoader() {
        try {
            String testPath = "test.png";
            TestImage = ImageIO.read(getClass().getResourceAsStream(testPath));

        } catch (IOException ex) {
            ex.printStackTrace();
        }

        addKeyListener(this);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.drawImage(TestImage, cordX, cordY, this);
    }

    public static void main(String[] args) {
        new TestProgram();
    }


    public void keyPressed(KeyEvent ke) {
        switch (ke.getKeyCode()) {
            case KeyEvent.VK_RIGHT: {
                cordX+=5;
            }
            break;
            case KeyEvent.VK_LEFT: {
                cordX-=5;
            }
            break;
            case KeyEvent.VK_DOWN: {
                cordY+=5;
            }
            break;
            case KeyEvent.VK_UP: {
                cordY-=3;
            }
            break;
        }
        repaint();
    }

    public void keyTyped(KeyEvent ke) {}

    public void keyReleased(KeyEvent ke) {}
}

Есть ли какое-нибудь решение, чтобы избежать этого?

РЕДАКТИРОВАТЬ: выше приведен полный рабочий код. Мне трудно включить в него двойной буфер. может ли кто-нибудь помочь мне в этой части?


person md1hunox    schedule 03.06.2012    source источник
comment
1) Чтобы быстрее получить помощь, опубликуйте SSCCE. 2) Не удлиняйте рамку. 3) Не рисуйте в контейнерах верхнего уровня (например, JFrame), вместо этого расширяйте JPanel 3) Установите предпочтительный размер панели и вызовите pack(), а не задавайте размер фрейма 4) Для не TLC переопределите paintComponent(), а не paint() 5) Запустите и измените графический интерфейс на EDT. 6) Для приложений Swing рассмотрите возможность использования привязок клавиш вместо KeyListener. 7) Во время развертывания вам, вероятно, потребуется получить доступ к изображению по URL-адресу.   -  person Andrew Thompson    schedule 03.06.2012
comment
@Эндрю Томпсон, хм, ты ответил на этот вопрос   -  person mKorbel    schedule 03.06.2012
comment
@mKorbel Я дал несколько советов. (пожимает плечами)   -  person Andrew Thompson    schedule 03.06.2012
comment
Я добавил рабочий пример. нужна помощь во включении части Double Buffer. Спасибо   -  person md1hunox    schedule 04.06.2012


Ответы (2)


Вы должны использовать буфер, чтобы избавиться от мерцания. Для изображений есть BufferedImage Buffer:

BufferedImage bf = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);

Затем вы рисуете свое изображение на экране следующим образом:

g.drawImage(bf, 0, 0, null);
person Stefan Fandler    schedule 03.06.2012
comment
1) Используйте ImageObserver, а не null, если он у вас есть. 2) Компоненты Swing по умолчанию имеют двойную буферизацию. - person Andrew Thompson; 03.06.2012

Не мерцает, рабочий код.

Repaint() не просто вызывает метод paint(). Метод repaint() фактически вызывает метод update(), а метод update() по умолчанию затем вызывает метод paint(). Поэтому просто переопределите метод update(). Также правильно рисуйте как BufferedImage, как указано выше.

Теперь это должно работать. Здесь это работало нормально. Я использовал только другой путь к изображению.

import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

public class TestProgram extends JFrame implements KeyListener {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private Image TestImage;
    private BufferedImage bf;
    private int cordX = 100;
    private int cordY = 100;

    public TestProgram() {
        setTitle("Testing....");
        setSize(500, 500);
        imageLoader();
        setVisible(true);
    }



    public void imageLoader() {
        try {
            String testPath = "test.png";
            TestImage = ImageIO.read(getClass().getResourceAsStream(testPath));

        } catch (IOException ex) {
            ex.printStackTrace();
        }

        addKeyListener(this);
    }

    public void update(Graphics g){
           paint(g);
    }

    public void paint(Graphics g){

        bf = new BufferedImage( this.getWidth(),this.getHeight(), BufferedImage.TYPE_INT_RGB);

    try{
    animation(bf.getGraphics());
    g.drawImage(bf,0,0,null);
    }catch(Exception ex){

    }
}

    public void animation(Graphics g) {
        super.paint(g);
        g.drawImage(TestImage, cordX, cordY, this);
    }

    public static void main(String[] args) {
        new TestProgram();
    }

    public void keyPressed(KeyEvent ke) {
        switch (ke.getKeyCode()) {
        case KeyEvent.VK_RIGHT: {
            cordX += 5;
        }
            break;
        case KeyEvent.VK_LEFT: {
            cordX -= 5;
        }
            break;
        case KeyEvent.VK_DOWN: {
            cordY += 5;
        }
            break;
        case KeyEvent.VK_UP: {
            cordY -= 3;
        }
            break;
        }
        repaint();
    }

    public void keyTyped(KeyEvent ke) {
    }

    public void keyReleased(KeyEvent ke) {
    }
}
person Guest1234    schedule 06.06.2012