Java Flackerndes Bild

RauchenderDachs

Cadet 4th Year
Registriert
Dez. 2012
Beiträge
70
Hi Leute

Ich hab vollgendes Problem. Ich versuche ein Quadrat auf einer vorgegebenen Route laufen zu lassen. Die Berechnung der neuen Koordinaten funktioniert auch soweit auch das einfügen auf den Background klappt. Allerdings flackert bei mir das Bild extrem. Ich hab schon das doubleBuffering ausprobiert.

Hier mal der Quelltext des GUI :
Code:
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package towerdefencev4;

import javax.swing.*;
import java.awt.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 */
public class GUI extends JFrame implements Runnable{

    /**
     * @param args the command line arguments
     */
  private Image dbImage;
   private Graphics dbGraphics;
    private Creep dasCreep= new Creep(40,25,this);
    int first = 1;
    public GUI(String title){
        super(title);
       
    }
    public static void main(String[] args) {
        GUI dieOberfläche = new GUI("TowerDefencev4");
        dieOberfläche.setSize(400,400);
        new Thread(dieOberfläche).start();
        dieOberfläche.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        dieOberfläche.setVisible(true);
    }
    @Override
    public void paint(Graphics gr){
        super.paint(gr);
        //Hintergrund
        gr.drawImage(Toolkit.getDefaultToolkit().getImage("../img/ground.gif"), 0, 0, this);
        //Creep 
        dasCreep.paintcreep(gr); 
        
    }

    @Override
    public void run() {
        while(true){
            
            dasCreep.move();
            repaint();
            try {
                Thread.sleep(40);
            } catch (InterruptedException ex) {
                Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    public void update(Graphics g)
   {
      //Double-Buffer initialisieren
      if (dbImage == null) {
         dbImage = createImage(
            this.getSize().width,
            this.getSize().height
         );
         dbGraphics = dbImage.getGraphics();
      }
      //Hintergrund löschen
      dbGraphics.setColor(getBackground());
      dbGraphics.fillRect(
         0,
         0,
         this.getSize().width,
         this.getSize().height
       );
      //Vordergrund zeichnen
      dbGraphics.setColor(getForeground());
      paint(dbGraphics);
      //Offscreen anzeigen
      g.drawImage(dbImage,0,0,this);
   }
    
    
}
Und von Creep:
Code:
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package towerdefencev4;

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

/**
 *
 */
public class Creep {
    int x, y;
    Component comp;
    boolean perreicht [] = new boolean [5];
    public Creep(int x, int y, Component comp){
        this.x=x;
        this.y=y;
        this.comp=comp;
    }
    public void paintcreep(Graphics gr){
        gr.drawImage(Toolkit.getDefaultToolkit().getImage("../img/creep.gif"), x, y, comp);
    }
    public void move(){
        boolean lr=false;
        boolean hr=false;
        if(x!=40 && perreicht[0]==false || y!=83 && perreicht[0]==false){
            movev(hr);
        }
        if(x==40 && y==83){
            perreicht[0]=true;
        }
        if(perreicht[0]==true){
            if(x!=237){
                moveh(lr);
            }
        }
        if(x==237 && y==83){
            perreicht[1]=true;
        }
        if(perreicht[1]==true){
            if(y!=206){
                movev(hr);
            }
        }
        if(x==237 && y==204){
            perreicht[2]=true;
        }
        if(perreicht[2]==true){
            if(x!=79){
                lr=true;
                moveh(lr);
            }
        }
        if(x==79 && y==205){
            perreicht[3]=true;
        }
        if(perreicht[3]==true){
            if(y!=350){
                movev(hr);
            }
        }
        if(x==79 && y==350){
            perreicht[4]=true;
        }
        if(perreicht[4]==true){
            
        }
    }
    public void moveh(boolean lr){//lr=left or right
        if(lr==false)
            x++;
        if(lr==true)
            x--;
    }

    public void movev(boolean hr){//hr = hoch oder runter
        if(hr==false)
            y++;
        if(hr==true)
            y--;
        
    }
}

Hoffe ihr könnt mir helfen

MFG RauchenderDachs
 
Würde das Bild in eine bufferedimage Laden und dann zeichnen. Hab's nur grob überflogen... Vielleicht hilfst.
 
...
import javax.swing.*;
import java.awt.*;
...

Ich kenn mich mit der GUI Programmierung unter Java nur eingeschränkt aus, aber ist es wirklich eine gute Idee, swing und awt zu mischen?!
 
Code:
    public static void main(final String[] args) {
        final GUI dieOberfläche = new GUI("TowerDefencev4");
        dieOberfläche.setSize(400, 400);
        new Thread(dieOberfläche).start();
        dieOberfläche.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        dieOberfläche.setVisible(true);
        dieOberfläche.add(new JPanel() {

            @Override
            public void paint(final Graphics g) {
                super.paint(g);
                //Hintergrund
                g.drawImage(Toolkit.getDefaultToolkit().getImage("../img/ground.gif"), 0, 0, this);
                //Creep
                dieOberfläche.getCreep().paintcreep(g);
            }
        });
    }

    Creep getCreep() {
        return dasCreep;
    }

Wenn du da ein double buffered JPanel dranhängst und dessen paint benutzt, statt im JFrame zu kritzeln, dann flackert es nicht mehr.

P.S.: Der Code hier ist nur quick & dirty zur Veranschaulichung. Swing ist schon etwas her bei mir. Ich erinnere mich, da gab es auch irgendein default panel, das man sich vom JFrame geben lassen konnte. Aber das findest du schon selbst raus.

P.P.S.: obligatorischer Buchtipp.
 
Zuletzt bearbeitet:
Danke das JPanel hat geholfen. Nur verstehe ich nicht ganz was du da gemacht hast. Könntest du mir das ein bisschen näher erklären?
 
Ich habe dem JFrame eine neue Komponente, ein JPanel, hinzugefügt. Man könnte diese auch noch mit dieOberfläche.setContentPane(new JPanel...) als content pane setzen, ich bin mir nur nicht mehr ganz sicher, ob das irgendwelche Nebenwirkungen hat. Bin zu sehr aus Swing raus.

In meiner Variante, wird einfach ein JPanel oben draufgelegt auf den JFrame und da diese auch eine paint-Methode hat (ich erinnere mich, man sollte besser paintComponent() überschreiben), kann ich dort die Zeichenlogik unterbringen, die bei dir bisher auf dem JFrame selbst passiert. JPanels sind by default double buffered (es gibt auch einen Konstruktor, um das zu deaktivieren) und eben dieses double buffering verhindert das Flackern.

Vielleicht noch zu dem Code-Konstrukt, falls du das nicht kennst: das ist eine anonyme Klasse. Man könnte auch (und sollte, wenn der Code an der Stelle größer wird) eine separate Klasse (entweder in der gleichen Datei oder in einer anderen) anlegen und diese dann instanziieren.

Code:
    @SuppressWarnings("serial")
    private static final class MyPanel extends JPanel {

        private final GUI dieOberfläche;

        private MyPanel(GUI dieOberfläche) {
            this.dieOberfläche = dieOberfläche;
        }

        @Override
        public void paint(final Graphics g) {
            super.paint(g);
            //Hintergrund
            g.drawImage(Toolkit.getDefaultToolkit().getImage("../img/ground.gif"), 0, 0, this);
            //Creep
            dieOberfläche.getCreep().paintcreep(g);
        }
    }

...


    public static void main(final String[] args) {
        final GUI dieOberfläche = new GUI("TowerDefencev4");
        dieOberfläche.setSize(400, 400);
        new Thread(dieOberfläche).start();
        dieOberfläche.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        dieOberfläche.setVisible(true);
        dieOberfläche.setContentPane(new MyPanel(dieOberfläche));
    }
 
Zuletzt bearbeitet:
Zurück
Oben