BufferedImage Teilbereich wieder transparent setzen

Ernesto95

Aktives Mitglied
Hallo zusammen !

Folgendes Problem: Ich erzeuge ein transparentes BufferedImage wie folgt

Java:
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration(); 
BufferedImage img = gc.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
Klappt ohne Probleme, ebenso das Zeichen auf diesem über den Graphics Object ...
Java:
g = (Graphics2D)img.getGraphics();
g.fillRect(0, 0, 50, 50);
g.fillRect(100, 100, 50, 50);
g.fillRect(200, 200, 50, 50);

Nun will ich aber z.B. das mittlere Rechteck wieder löschen und diesen Teilbereich wieder Transparent setzen.
Folgendes klappt nicht, da ich mit einer Transparenz ja nichts übermalen kann (-> eigentlich logisch ;-)).
Java:
g.setColor(new Color(0,0,0,0));
g.fillRect(100, 100, 50, 50);

Warum das aber nicht funktioniert ist mir noch ein Rätsel ...
Java:
g.setBackground(new Color(0,0,0,0));
g.clearRect(100, 100, 50, 50);

... ganz im Gegenteil, die API schlägt vor eher die erste Lösung zu nutzen die ja beim Thema Transparenz meiner Meinung nach nicht klappen kann.

JAVA API clearRect();
Clears the specified rectangle by filling it with the background color of the current drawing surface. This operation does not use the current paint mode.
Beginning with Java*1.1, the background color of offscreen images may be system dependent. Applications should use setColor followed by fillRect to ensure that an offscreen image is cleared to a specific color.


Hat jemand einen Tip wie ich das Rechteck löschen und den Bereich wieder Transparent setzen kann ? Oder muss ich wirklich umständlich das ganze BufferedImage neu erstellen und dann das unerwünschte Rechteck weglassen ?

Vielen Dank !
 
Zuletzt bearbeitet von einem Moderator:

JCODA

Top Contributor
Wenn mich nicht alles täuscht speichert ein BufferedImage die Farbdaten in einem int[][] ( naja zumindest bei RGBA) und dort ist nunmal nur "Platz" für eine Farbe, stell dir vor, das Image würde "jegliche" vorherigen Werte speichern, der Platzverbrauch wäre enorm. Also bleibt dir wohl nicht, als dein
BufferedImage neu erstellen und dann das unerwünschte Rechteck weglassen ?
Wenns dynamischer sein soll ggf. die Rechtecke mit Farbe in ner Liste speichern.
 

Ernesto95

Aktives Mitglied
(...)und dort ist nunmal nur "Platz" für eine Farbe, stell dir vor, das Image würde "jegliche" vorherigen Werte speichern, der Platzverbrauch wäre enorm. (...)

Hi !

Ich glaube du hast micht nicht richtig verstanden. Ich suche nicht nach einer "Zurück"-Methode um das Rechteck zu löschen (dazu bräuchte ich ja dann die von dir angesprochene Speicherung der vorherigen Werte). Ich suche nach einer Möglichkeit, das mittlere Rechteck zu löschen und den Platz wieder Transparent zu setzen.

Wäre z.B. der Hintergrund der Zeichenfläche blau und das zu löschende Rechteck rot würde ich einfach in den Bereich des roten Rechtecks ein gleich großes blaues Rechteck zeichnen und schon wäre das rote Rechteck verschwunden. Da der Hintergrund aber Transparent ist klappt das nicht da ich das Rechteck logischerweise nicht mit einem transparenten Rechteck übermalen kann. Können schon, man würde nur keinen Unterschied bemerken da das alte rote Rechteck durch die Transparenz durchscheint ;-)

Was ich brauche ist eine Funktion die in einem definierten Bereich alle Farbinformationen löscht und diesen Bereich auf 100% Transparenz setzt.
 
Zuletzt bearbeitet:
S

Spacerat

Gast
Meines Wissens funktioniert das am einfachsten mit "<BufferedImage>.setRGB()" (welche von beiden ist egal). Evtl. funktioniert auch "<Graphics>.setPaintMode()" bevor das Rechteck gezeichnet bzw. gelöscht wird wird.
 

JCODA

Top Contributor
Stimmt, ich hab's falsch verstanden, dafür müsste ich nu aber eine Lösung liefern können:
laut java - Transparency in bufferedimage objects - Stack Overflow

hilft ein einfaches:

Java:
g.fillRect(0, 0, 50, 50);
g.fillRect(100, 100, 50, 50);
g.fillRect(200, 200, 50, 50);		
g.setComposite(AlphaComposite.Clear);	
g.fillRect(100, 100, 50, 50);
g.setComposite(AlphaComposite.Src);

Ich habs auch ausprobiert und es klappt.
 
S

Spacerat

Gast
@JCODA: "setComposite()" ist Graphics2D. Ich hab' überlesen, das der TO ohnehin casted und deswegen weggelassen.
@TO: Statt "(Graphics2D) img.getGraphics()" "img.createGraphics()". Kommt aufs selbe raus, ohne cast.
 

Ernesto95

Aktives Mitglied
@Spacerat / JCODA: 2 Danke für euch, klappt :)

Allerdings hab ich nen Folgefehler, vielleicht könnt ihr da auch helfen ...

Folgendes: Dieses BufferedImage ist Teil einer GameLoop. Über Active Rendering wird die repaint() Methode des darstellenden JPanels umgangen und direkt in den Graphic Context des JPanels gezeichnet.

Um wieder bei obigem Beispiel mit den 3 Rechtecken zu bleiben. Ich zeiche die 3 Rechtecke in das BufferedImage. Das BufferedImage zeichne ich danach in das grahics Object des JPanels. Im nächsten Schleifendurchgang lösche ich in dem BufferedImage das mittlere Quadrat und setze den Bereich wie oben von JCODA beschrieben auf Transparent. Klappt !

Problem ist nur: Im Graphics Object des Panels ist weiterhin das Bild mit den 3 Rechtecken hinterlegt. Zeichne ich jetzt das neue BufferedImage in das graphics Object des Panels so scheint das mittlere Quadrat durch die Transparenz durch und es scheint als wurde nichts geändert.

Wenn ich vorher im Graphics Object des JPanels ebenfalls mit dem von JCODA beschriebenen Code den Hintergrund auf Transparant setze funktioniert zwar die Anzeige, allerdings hab ich dann das bekannte flackern da ich direkt auf das angezeigte Object zeichne ...

Gibts vielleicht irgendwie die Möglichkeit statt das BufferedImage in das Graphics Object des Panels zu malen z.B. das Graphics Object des Panels mit dem des BufferedImages zu tauschen ? Oder irgendeine andere Möglichkeit ?

Sorry für eventuell dumme Fragen, ist mein erstes Swing Project bei dem ich mehr mit Grafiken mache als nen png als Hintergrund einzubinden daher hab ich noch nicht 100% den Durchblick ^^
 

Michael...

Top Contributor
So ganz habe ich es nicht verstanden. Kannst Du nicht einen Teil als "Hintergrund" auf ein BufferdImage und den sich ändernden Umfang direkt in der paintComponent zeichnen?
 

Ernesto95

Aktives Mitglied
So ganz habe ich es nicht verstanden. Kannst Du nicht einen Teil als "Hintergrund" auf ein BufferdImage und den sich ändernden Umfang direkt in der paintComponent zeichnen?

Ne, da ich mit Aktive Rendering den Zeitpunkt des Neuzeichnens exakt selbstbestimmen möchte und daher die PaintComponents Methode nicht nutze, da diese über repaint aufgerufen wird und repaint nicht unmittelbar ausgeführt wird ...
 

Ernesto95

Aktives Mitglied
So bin wieder zu Hause und werde mal ein wenig Code posten, in der Hoffnung das ich somit das Problem deutlicher machen kann und jemand eine Lösung hat. Der Code ist noch sehr BETA und nicht dokumentiert ^^

Das ganze soll eine Utility Klasse werden, welche zum Beispiel als Game Loop brauchbar wäre.

Hierzu wird eine Zeichenfläche zur Verfügung gestellt (als JComponent), welche der User frei nach seinen Wünschen plazieren kann. Direkt aufs JFrame, aber wenn er möchte auch zig mal verschachtelt irgendwo in seinem Design wo er etwas animiertes benötigt.

Der Code der Zeichenfläche ist wie folgt:

AnimationLoopCanvas
Java:
public class AnimationLoopCanvas extends JComponent{
    
    public AnimationLoopCanvas(int width, int height){
        super();
        this.setOpaque(false);
        this.setPreferredSize(new Dimension(width,height));
        this.setIgnoreRepaint(true);
    }
    
    protected void draw(BufferedImage img){
        Graphics g = this.getGraphics();
        g.drawImage(img, 0, 0, this);
    }
}

Diese Zeichenfläche wird durch die Klasse AnmiationLoop zur Verfügung gestellt. Die Klasse die die AnimationLoop aufruft implementiert das Interface AnimationRequester und stellt somit die Methoden update() und draw(Grahpics2D) zur Verfügung.

AnimationRequester
Java:
public interface AnimationRequester {

    public void update();
    public void draw(Graphics2D g);
}

AnimationLoop wiederum bietet verschiedene Einstellungen. So z.B. ob ein "jungfräuliches" Graphic2D Objekt an draw(Graphic2D) übergeben wird oder nicht.

FALSE = es wird immer das gleiche Graphic2D Object genutzt
TRUE = es wird zwar auch das gleiche benutzt, dieses aber vorher bearbetet

Bearbeitet heißt, ist ein Hintergrundbild definiert so wird das Hintergrundbild in das Grahic2D gezeichnet, ist eine Hintergrundfarbe definiert so wird so wird diese gezeichnet. Ist keins von beidem definiert (also sowohl backgroundImage == null als auch backgrondColor == null, so wird ein transparentes Graphic2D übergeben.

Ich poste jetzt die gesamte Klasse, falls jemand den Fehler reproduzieren möchte, wichtig für den Fehler den ich habe ist eigentlich nur die Schleife in Zeile 204-215 in Verbindung mit den Methoden createImage und prepareGraphics2D in den Zeilen 239 bis 259.

AnimationLoop
Java:
public final class AnimationLoop {
    
    // ********************************************************************************
    // ENUM classes *******************************************************************
    // ********************************************************************************
    public static enum Counter{
        DO_NOT_SHOW(false, 0),
        NORTH_WEST(true, 1),
        NORTH(true, 2),
        NORTH_EAST(true, 3),
        SOUTH_WEST(true, 4),
        SOUTH(true, 5),
        SOUTH_EAST(true, 6);
        
        private int position;
        private boolean show;
        
        Counter(boolean show, int position){
            this.position = position;
            this.show = show;
        }
        
        protected int getPosition(){
            return position;
        }
        
        protected boolean isShow(){
            return show;
        }   
    }

    // ********************************************************************************
    // Declaration of all class variables *********************************************
    // ********************************************************************************
    private final int SECOND_IN_NANOS = 1000000000;
    private AnimationLoopCanvas canvas;
    private AnimationRequester requester;
    private int width, height;
    private double requestedUpdatesPerSecond = 30;
    private double requestedDrawingsPerSecond = 30;
    boolean running;
    boolean paused;
    private Counter counter = Counter.DO_NOT_SHOW;
    private long sleepTime = 1;
    private Color backgroundColor;
    private BufferedImage backgroundImage;
    private boolean provideVirginCanvas = true;
    
    // ********************************************************************************
    // Constructors *******************************************************************
    // ********************************************************************************
    public AnimationLoop(AnimationRequester requester, int width, int height){
        this.requester = requester;
        this.width = width;
        this.height = height;
        canvas = new AnimationLoopCanvas(width, height);
    }
    
    public AnimationLoop(AnimationRequester requester, int width, int height, double requestedUpdatesPerSecond, 
            double requestedDrawingsPerSecond){
        this(requester, width, height);
        this.requestedUpdatesPerSecond = requestedUpdatesPerSecond;
        this.requestedDrawingsPerSecond = requestedDrawingsPerSecond;
    }
    
    public AnimationLoop(AnimationRequester requester, int width, int height, double requestedUpdatesPerSecond, 
            double requestedDrawingsPerSecond, Color backgroundColor){
        this(requester, width, height, requestedUpdatesPerSecond, requestedDrawingsPerSecond);
        this.backgroundColor = backgroundColor;
    }
    
    public AnimationLoop(AnimationRequester requester, int width, int height, double requestedUpdatesPerSecond, 
            double requestedDrawingsPerSecond, BufferedImage backgroundImage){
        this(requester, width, height, requestedUpdatesPerSecond, requestedDrawingsPerSecond);
        this.backgroundImage = backgroundImage;
    }
    
    
    // ********************************************************************************
    // GETTER methods******************************************************************
    // ********************************************************************************
    public AnimationLoopCanvas getCanvas(){
        return canvas;
    }

    public int getWidth() {
        return width;
    }
    
    public int getHeight() {
        return height;
    }

    public double getRequestedDrawingsPerSecond() {
        return requestedDrawingsPerSecond;
    }

    public double getRequestedUpdatesPerSecond() {
        return requestedUpdatesPerSecond;
    }

    public Counter getCounter() {
        return counter;
    }

    public long getSleepTime() {
        return sleepTime;
    }

    public Color getBackgroundColor() {
        return backgroundColor;
    }

    public BufferedImage getBackgroundImage() {
        return backgroundImage;
    }

    public boolean isProvideVirginCanvas() {
        return provideVirginCanvas;
    }
    
    
    
    
    
    // ********************************************************************************
    // SETTER methods******************************************************************
    // ********************************************************************************
    public void setRequestedDrawingsPerSecond(int requestedDrawingsPerSecond) {
        this.requestedDrawingsPerSecond = requestedDrawingsPerSecond;
    }

    public void setRequestedUpdatesPerSecond(int requestedUpdatesPerSecond) {
        this.requestedUpdatesPerSecond = requestedUpdatesPerSecond;
    }

    public void setCounter(Counter counter) {
        this.counter = counter;
    }

    public void setSleepTime(long sleepTime) {
        this.sleepTime = sleepTime;
    }

    public void setBackgroundColor(Color backgroundColor) {
        this.backgroundColor = backgroundColor;
    }

    public void setBackgroundImage(BufferedImage backgroundImage) {
        this.backgroundImage = backgroundImage;
    }

    public void setProvideVirginCanvas(boolean provideVirginCanvas) {
        this.provideVirginCanvas = provideVirginCanvas;
    }
    
    

    // ********************************************************************************
    // other PUBLIC methods ***********************************************************
    // ********************************************************************************
    public void start() {
        Thread loop = new Thread()
        {
            @Override
            public void run()
            {
                gameLoop();
            }
        };
        running = true;
        paused = false;
        loop.start();
    }
    
    // ********************************************************************************
    // PRIVATE methods ****************************************************************
    // ********************************************************************************
    private void gameLoop() {
        final double timeBetweenUpdates = SECOND_IN_NANOS / requestedUpdatesPerSecond;
        final double timeBetweenDrawings = SECOND_IN_NANOS / requestedDrawingsPerSecond;
        long lastUpdateTime = 0;
        long lastDrawingTime = 0;
        long startTime;
        long lastCounterCalculationTime = System.nanoTime();
        int updateCounter = 0;
        int drawingCounter = 0;
        int lastUpdateCounter = 0;
        int lastDrawingCounter = 0;
        BufferedImage img;
        Graphics2D g;
        
        img = createImage();
        g = img.createGraphics();
        prepareGraphics2D(g);
        while(running){
            while(!paused){
                startTime = System.nanoTime();
                if(startTime - lastUpdateTime >= timeBetweenUpdates){
                    updateCounter++;
                    lastUpdateTime = startTime;
                    requester.update();
                }
                if(startTime - lastDrawingTime >= timeBetweenDrawings){
                    drawingCounter++;
                    lastDrawingTime = startTime;
                    if(provideVirginCanvas){
                        prepareGraphics2D(g);
                    }
                    requester.draw(g);
                    if(counter.isShow()){
                        drawCounter(g, lastUpdateCounter, lastDrawingCounter);
                    }
                    canvas.draw(img);
                }
                if(startTime-SECOND_IN_NANOS >= lastCounterCalculationTime){
                    lastCounterCalculationTime = System.nanoTime();
                    lastUpdateCounter = updateCounter;
                    lastDrawingCounter = drawingCounter;
                    updateCounter=0;
                    drawingCounter=0;
                }
                while(!(System.nanoTime() - lastUpdateTime >= timeBetweenUpdates)
                        && !(System.nanoTime() - lastDrawingTime >= timeBetweenDrawings)
                        && !(System.nanoTime() - SECOND_IN_NANOS >= lastCounterCalculationTime)){
                    Thread.yield();
                    try {
                        Thread.sleep(sleepTime);
                    } 
                    catch (InterruptedException ex) {
                        Logger.getLogger(AnimationLoop.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        }
        g.dispose();
    }
    
    private BufferedImage createImage(){
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice gs = ge.getDefaultScreenDevice();
        GraphicsConfiguration gc = gs.getDefaultConfiguration(); 
        return gc.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
    }
    
    private void prepareGraphics2D(Graphics2D g){
        if (backgroundImage != null){
            g.drawImage(backgroundImage, 0, 0, canvas);
        }
        else if (backgroundColor != null) {
            g.setColor(backgroundColor);
            g.fillRect(0, 0, width, height);
        }
        else {
            g.setComposite(AlphaComposite.Clear);   
            g.fillRect(0, 0, width, height);
            g.setComposite(AlphaComposite.Src);
        }
    }
    
    private void drawCounter(Graphics2D g, int lastUpdateCounter, int lastDrawingCounter){
        final int COUNTER_WIDTH = 70;
        final int COUNTER_HEIGHT = 35;
        int x=0;
        int y=0;
        Color old = g.getColor();
        switch(counter.getPosition()){
            case 1:
                break;
            case 2:
                x = (width-COUNTER_WIDTH)/2;
                break;
            case 3:
                x = width-COUNTER_WIDTH;
                break;
            case 4:
                y = height-COUNTER_HEIGHT;
                break;
            case 5:
                x = (width-COUNTER_WIDTH)/2;
                y = height-COUNTER_HEIGHT;
                break;
            case 6:
                x = width-COUNTER_WIDTH;
                y = height-COUNTER_HEIGHT;
                break;   
        }
        g.setColor(Color.WHITE);
        g.fillRect(x, y, COUNTER_WIDTH, COUNTER_HEIGHT);
        g.setColor(Color.BLACK);
        g.drawString("UPS: "+lastUpdateCounter, x+5, y+15);
        g.drawString("FPS: "+lastDrawingCounter, x+5, y+30);
        g.setColor(old);
    }
}

Als Testklasse dienen TestFrame und TestStart. Diese machen eigentlich nichts weiter als ein Rechteck der Größe 100x100 zu zeichnen welches sich mit 50fps von links oben nach rechts unten bewegen soll.

TestStart
Java:
public class TestStart {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                TestFrame frame = new TestFrame();
            }
        });
    }
}

TestFrame
Java:
public class TestFrame extends JFrame implements AnimationRequester {
    
    private AnimationLoop loop;
    private int x=0;
    private int y=0;
    
    public TestFrame(){
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle("AnimationLoop Test Frame");
        loop = new AnimationLoop(this, 800, 600, 50, 50);
        loop.setCounter(AnimationLoop.Counter.NORTH_WEST);
        //loop.setBackgroundColor(Color.GREEN);
        //loop.setProvideVirginCanvas(false);
        
        
        JPanel panel = new JPanel();
        panel.setBackground(Color.blue);
        panel.setLayout(null);
        panel.setPreferredSize(new Dimension(800,600));
        panel.add(loop.getCanvas());
        loop.getCanvas().setBounds(0, 0, 800, 600);
        this.add(panel);
        this.pack();
        this.setResizable(false);
        this.setVisible(true);
        loop.start();
    }

    @Override
    public void update() {
        System.out.println("update calling ...");
        x++;
        y++;
    }

    @Override
    public void draw(Graphics2D g) {
        System.out.println("DRAW CALLING ...");
        g.setColor(Color.red);
        g.fillRect(x, y, 100, 100);
    }

}

Um zu simulieren das ein Nutzer die Zeichenfläche nicht direkt aufs JFrame sondern verschachtelt irgendwo in seinem Design einfügt habe ich die Zeichenfläche in ein Panel mit blauem Hintergrund gepackt.

Übergebe ich ein Hintergrundbild (ohne Transparenz), funktioniert für virginCanvas sowohl true als auch false (true = das Rechteck wandert, false = es wird immer ein neues Rechteck gezeichnet ohne das alte zu löschen, somit entsteht eine dicke Linie)

Das gleiche wenn ich eine Hintergrundfarbe übergebe, beide virginCanvas Einstellungen funktionieren.

Nur wenn beides den Wert null hat und somit eine transparente Zeichenfläche übergeben werden soll funktioniert es nicht. Der Fehler liegt hier im AnimationCanvas. Das BufferedImage was übergeben wird ist Transparent, mit Ausnahme des gezeichneten Rechtecks. Bei virginCanvas = false fällt der Fehler noch nicht auf, da auf dem BufferedImage alle bisher gezeichneten Rechtecke enthalten bleiben.

Bei virgin Canvas = true aber wird es offensichtlich. Beim z.B. 200 Schleifendurchlauf wird ein transparentes BufferedImage mit einem Rechteck der Größe 100x100 auf Position 200,200 an AnimationCanvas übergeben.

Diese zeichnet das Bild.

Das Problem ist, das das Graphics Object von AnimationCanvas nicht leer ist, sondern auf diesem wurden bereits 200 Bilder gezeichnet, und da der Bereich der Rechtecke der vorherigen 200 Bilder jeweils von transparenten Bildern "übermalt" wird verschwindet er nicht, sondern bleibt weiter sichtbar. Somit ist die Ausgabe bei virginCanvas = true identisch mit virginCanvas = false.

Frage: Wie kann ich im AnimationCanvas das Graphic Object "reseten", so das es jedesmal wieder komplett Transparent ist bevor ich das Bild zeichne, ohne das unerwünschte flackern welches Auftritt wenn ich auf dem angezeigten Graphics Object zeichne ? Repaint() in Verbindung mit der Einstellung setOpaque(false) ist keine Lösung da ich bestimmen will wann gezeichnet wird, repaint() aber halt irgendwann das Zeichnen anstösst.

So, das war mein gesamter Input, wer es bis hierhin geschafft hat der hat nun 3 Möglichkeiten zu antworten:

1. Ja sag das doch gleich, hier ist die Lösung: ...

2. Interessant, aber Lösung ? Keine Ahnung ...

3. Meine Fresse, wat nen s****** versuchst du denn da ???

Wie auch immer die Antwort lautet, alleine fürs lesen sag ich schonmal Danke ;-)
 
Zuletzt bearbeitet:
S

Spacerat

Gast
Also für mich war so viel code nun gar nicht nötig. Faktisch bleibt der Graphics-Kontext des Panels von deinen aktuellen Zeichenkünsten ja unberührt. Das was JCODA da auf das BI anwendet, muss nun direkt auf den Kontext des Panels angewendet werden, denn dieser hat ja noch die Farbinformationen des vorherigen Zeichenvorgangs. Theoretisch müsstest du, bevor der neue Rendervorgang startet, den gesamten Panel mit einer Hintergrundfarbe löschen. diese Farbe sollte aber diesmal nicht transparent sein.
Ich erinner mal daran, wie ein ordinärer GL-Renderloop beginnt:
Java:
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
will sagen: Da macht man's nicht anders.
 

Michael...

Top Contributor
Ne, da ich mit Aktive Rendering den Zeitpunkt des Neuzeichnens exakt selbstbestimmen möchte und daher die PaintComponents Methode nicht nutze, da diese über repaint aufgerufen wird und repaint nicht unmittelbar ausgeführt wird ...
Was hat das eine mit dem anderen zu tun? Klar nutzt man beim Active Rendering nicht den Swing Paint-Mechanismus, aber auch das Image musst Du auf den Graphics Kontext der Komponente zeichnen. Mein Vorschlag war ja nur, dass Du den Hintergrund auf dem Image hälst und die variablen Objekte direkt in den Graphics Kontext zeichnest.
 

Ernesto95

Aktives Mitglied
Sorry, aber eure Lösungen gehen immer noch an meinem Problem vorbei. Die Komponente die das animierte Bild anzeigt muss nicht zwingend die Hauptkomponente der Anwendung sein.

Ich versuch nochmal ganz abstrakt zu erklären ohne das das Beispiel irgendeinen praktischen Sinn ergibt.

Gegeben sei ein JFrame. Auf dieses lege ich ein JPanel auf die gesamte Größe und male in dieses Panel irgendein Hintergrundbild (in meinem Beispiel oben ist das Hintergrundbild einfach die Farbe blau).

Nun gebe ich diesem Panel das Borderlayout, und da es sich vielleicht um eine Anwendung für eine Autovermietung handelt möchte ich das im BorderLayout.SOUTH ein Auto animiert von links nach rechts fährt. Dazu binde ich meine animierte Komponente (eine JComponent) in den South Bereich desJPanels ein.

Das Problem: Während das Auto fährt soll die JComponent weiterhin Transparent bleiben (mit Ausnahme des Autos), so das das Hintergrundbild des JPanels weiterhin auch im Bereich meiner animierten JComponent sichtbar bleibt.

Dementsprechend ist das "Löschen" der Grafikinformationen der JComponent durch überschreiben mit einer nicht transparenten Farbe wie es Spacerat vorschlägt nicht zielführend, da somit das Hintergrundbild des JPanels im SOUTH Bereich übermalt wird.

Und Michael, was du vorschlägst mache ich doch bereits wenn ich dich nicht komplett falsch verstehe. Das Problem ist nur, wenn das animierte Auto einmal den Pixel auf der JComponent auf z.B. Position (10,10) rot eingefärbt hat, dann kann ich der JComponent 100x ein neues Hintergrundbild zum zeichnen übergeben, solange beim Hintergrundbild der Pixel auf Position (10,10) transaprent ist bleibt der Pixel auf der JComponent auf Position (10,10) rot.

Und diesen verdammten roten Pixel kann ich nicht durch übermalen mit der Hintergrundfarbe "löschen", denn da die Hintergrundfarbe Transparent ist muss ich ihn irgendwie wieder transparent gesetzt bekommen. Hat Sun denn wirklich die löscheFarbinformationen() Funktion vergessen ? *grummel*
 
S

Spacerat

Gast
Okay... dann darfst du weder den Graphics-Kontext deines Panels noch jenen der Component darunter verwenden.
Evtl. geht's ja ganz anders, ohne active Rendering. Also zurück zu paintComponent und in eine JGlassPane gezeichnet. Hier werden durch eine solche ganze GUIS ein- und ausgefadet. Ich selbst hatte damit allerdings noch nie etwas zu tun, aber sieht zumindest schon mal vielversprechend aus.
 

Ernesto95

Aktives Mitglied
Hi !

Also das mit der JGlasspane scheint auf jeden Fall die Lösung für ein anderes Problem zu sein worüber ich mir gerade Gedanken mache, was ich aber noch garnicht publik gemacht hatte. Also danke fürs Gedankenlesen :)

Für hier aber auch keine Lösung, da die JGlassPane sich übers komplette JFrame legt (zumindest so wie ich es verstehe), meine AnimationLoop aber komplett gekapselt irgendwo auch nur in einem Teilbereich laufen soll ...

Naja, auf jeden Fall danke für eure Hilfe und Zeit, falls noch wem was einfällt meldet euch, ansonsten google und versuche ich weiter. Wenn ich irgendeinen praktikablen Workaround finde melde ich mich !
 
S

Spacerat

Gast
Okay... dann sind wir mal Kreativ und basteln uns diese GlassPane-Geschichte selbst und zwar mit JLayeredPane, "setLayer((Component) glassPane, 0)" und "setLayer((Component) originalPane, -1)". Hoffentlich sind auf der originalPane dann nicht auch noch Buttons.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
Mr.Strobel BufferedImage Exportieren Eclipse Java Basics - Anfänger-Themen 14
A BufferedImage zeigt nur schwarz Java Basics - Anfänger-Themen 3
A BufferedImage Pixel Java Basics - Anfänger-Themen 7
pkm Best Practice BufferedImage in JPane darstellen - aber wie? Java Basics - Anfänger-Themen 22
T BufferedImage in Jar Java Basics - Anfänger-Themen 8
C Problem beim laden eines BufferedImage Java Basics - Anfänger-Themen 2
S BufferedImage heller/dunkler machen mit RescaleOp Java Basics - Anfänger-Themen 2
D Jpg in BufferedImage Reader oder Array ablegen? Java Basics - Anfänger-Themen 5
F BufferedImage Speicher Nutzung Java Basics - Anfänger-Themen 2
S BufferedImage Java Basics - Anfänger-Themen 2
M BufferedImage performant einlesen Java Basics - Anfänger-Themen 5
A BufferedImage in Android einbinden - Bild spiegeln -wie? Java Basics - Anfänger-Themen 4
O BufferedImage drehen, falsch positioniert Java Basics - Anfänger-Themen 5
K BufferedImage, Bilder laden Java Basics - Anfänger-Themen 15
H BufferedImage DPI verändern Java Basics - Anfänger-Themen 5
S jpeg bzw bufferedimage als PDF Speichern Java Basics - Anfänger-Themen 13
W von Graphics in BufferedImage Java Basics - Anfänger-Themen 10
H BufferedImage Java Basics - Anfänger-Themen 5
F BufferedImage aus short[][][] Java Basics - Anfänger-Themen 3
Luk10 NPE bei BufferedImage[] Java Basics - Anfänger-Themen 4
S BufferedImage mit farbwerten füllen Java Basics - Anfänger-Themen 11
I Probleme beim Laden eins BufferedImage Java Basics - Anfänger-Themen 8
P BufferedImage als raw speichern Java Basics - Anfänger-Themen 3
C BufferedImage + Popup/Overlay Java Basics - Anfänger-Themen 2
E BufferedImage drucken Java Basics - Anfänger-Themen 3
R BufferedImage in JLabel Java Basics - Anfänger-Themen 2
G Serialisiertes BufferedImage wieder einlesen Java Basics - Anfänger-Themen 13
G Jpanel -> BufferedImage konvertieren Java Basics - Anfänger-Themen 7
G BufferedImage in Applet laden Java Basics - Anfänger-Themen 8
Q BufferedImage aus Bild in jar Java Basics - Anfänger-Themen 2
? BufferedImage löschen Java Basics - Anfänger-Themen 4
F Farben eines ganzen BufferedImage invertieren Java Basics - Anfänger-Themen 2
K Graphics2D und BufferedImage Java Basics - Anfänger-Themen 3
D wie kann ich ein BufferedImage komprimieren? Java Basics - Anfänger-Themen 7
reibi TIFF nach BufferedImage wandeln Java Basics - Anfänger-Themen 72
reibi Farbiges BufferedImage umwandeln zu 2farbig SchwarzWeiss Java Basics - Anfänger-Themen 7
E nullpointer bei BufferedImage Java Basics - Anfänger-Themen 2
M BufferedImage erzeugt OutOfMemoryError Java Basics - Anfänger-Themen 10
B Vorteil von Graphic2D und BufferedImage? Java Basics - Anfänger-Themen 6
U BufferedImage anzeigen, imageIcon oder paintComponent(); Java Basics - Anfänger-Themen 6
X Image nach BufferedImage wandeln ? Java Basics - Anfänger-Themen 9
T BufferedImage kopieren Java Basics - Anfänger-Themen 6
G Image -> BufferedImage Java Basics - Anfänger-Themen 4
M Image/BufferedImage Java Basics - Anfänger-Themen 4
T Multiple BufferedImage Java Basics - Anfänger-Themen 3
DrahtEck Schleife soll wieder da anfangen wo ich es möchte ! Java Basics - Anfänger-Themen 17
G JTree speichern und wieder einlesen Java Basics - Anfänger-Themen 5
W In alten Code zurück- und dort wieder zurechtfinden? Java Basics - Anfänger-Themen 17
I Passwort in Datenbank speichern um später wieder auszulesen Java Basics - Anfänger-Themen 5
Temsky34 Wie bekomme ich dieses Java-Warning wieder weg? Java Basics - Anfänger-Themen 2
T j.u.Scanner(Sys.in).nextLine() wieder schließen? Java Basics - Anfänger-Themen 5
f3mys Objektwerte in Liste speichern und wieder abrufen Java Basics - Anfänger-Themen 23
O Text mit Regex trennen und wieder zusammenbauen Java Basics - Anfänger-Themen 5
Naxon89 Input/Output Ein PDF in einem BLOB umwandeln um ihn dann als PDF wieder anzuzeigen Java Basics - Anfänger-Themen 3
H JavaFX Hintergrundfarbe ändern, warten, Hintergrundfarbe wieder ändern Java Basics - Anfänger-Themen 34
MichelNeedhelp Brauche zu diesem Labyrinth ein Skript? Der Hamster soll im Urzeigersinn das ganze Labyrinth abgehen und wieder an seinem Ursprungsplatz sein. Java Basics - Anfänger-Themen 40
D Codeblöcke, die immer wieder im Programmverlauf benötigt werden Java Basics - Anfänger-Themen 5
TimoN11 Array -> Schleife wieder von vorne durchlaufen lassen Java Basics - Anfänger-Themen 1
JD_1998 Arrays einlesen, zwischenspeichern und wieder ausgeben Java Basics - Anfänger-Themen 8
M Regex Probleme (mal wieder) Java Basics - Anfänger-Themen 3
J Selektiertes Element von jComboBox zwischenspeichern und wieder einsetzen Java Basics - Anfänger-Themen 0
S Nutzereingabe splitten und in string array wieder ausgeben. Java Basics - Anfänger-Themen 1
I wieder mit einer Umwandelung habe ich Problem (diesmal von char Array zu char) Java Basics - Anfänger-Themen 1
N Wie kann ich einen String wieder zusammensetzen und ausgeben lassen? Java Basics - Anfänger-Themen 9
C Array-Eintrag wieder auf Null setzen Java Basics - Anfänger-Themen 3
W Verschachtelte Objekte wieder auspacken Java Basics - Anfänger-Themen 3
M Array immer wieder um ein Element erweitern Java Basics - Anfänger-Themen 6
CptK Methoden Event bei gedrückter Maustaste immer wieder ausführen Java Basics - Anfänger-Themen 1
CptK Klassen Event bei gedrückter Maus immer wieder mit Pause ausführen Java Basics - Anfänger-Themen 2
J Geld speichern und wieder auslesen Java Basics - Anfänger-Themen 10
M JTextField blitzt immer wieder nur auf Java Basics - Anfänger-Themen 12
CptK Datentypen Verdrehte Wörter wieder herstellen Java Basics - Anfänger-Themen 21
J Timer bauen, Main Methode immer wieder neu starten Java Basics - Anfänger-Themen 13
I Methoden Schleife immer wieder durchlaufen lassen Java Basics - Anfänger-Themen 15
F Immer wieder gleiche Zufallszahl? Java Basics - Anfänger-Themen 4
M Schleifenergebnis in selbiger wieder verwenden Java Basics - Anfänger-Themen 7
L Methoden Rekursion gibt alten Wert wieder Java Basics - Anfänger-Themen 37
L jar, class, java und wieder zurück Java Basics - Anfänger-Themen 8
M aus Fenster anderes Fenster öffnen und wieder umgekehrt Java Basics - Anfänger-Themen 5
J Fenster wieder unsichtbar machen Java Basics - Anfänger-Themen 2
J Auslesen/speichern und wieder einlesen Java Basics - Anfänger-Themen 7
S Sound stoppen und nach Pause wieder abspielen Java Basics - Anfänger-Themen 6
T while schleife starten , beeneden und wieder Starten Java Basics - Anfänger-Themen 8
I Zähler, der erst wieder zählt nachdem Pixel wieder andere Farbe hat Java Basics - Anfänger-Themen 2
B javax.ejb.Timer wieder starten? Java Basics - Anfänger-Themen 0
N Methode auslagern mal wieder Java Basics - Anfänger-Themen 8
F Inhalt einer Variable auswerten, die sich immer wieder ändert Java Basics - Anfänger-Themen 1
B ja ja schon wieder einer mit einer public static void main(string[] args) Frage... Java Basics - Anfänger-Themen 8
Bluedaishi for schleife um Dateien wieder zusammen zu fügen Java Basics - Anfänger-Themen 11
I SHA512 verschlüsseln und dann wieder auslesen? Java Basics - Anfänger-Themen 35
F Timer abbrechen und wieder starten Java Basics - Anfänger-Themen 5
J KeyListener - mal wieder... Java Basics - Anfänger-Themen 2
B Listener beim Laden (deserialize) wieder hinzufügen bzw. mitspeichern? Java Basics - Anfänger-Themen 3
GadgetSofa .txt Datei erstellen und gleich wieder Löschen? Java Basics - Anfänger-Themen 12
D Bild für ein paar Sekunden einblenden und wieder ausblenden Java Basics - Anfänger-Themen 1
M Tabelle aktualisieren (mal wieder) Java Basics - Anfänger-Themen 10
M Erste Schritte Tabelle aktualisieren (mal wieder) Java Basics - Anfänger-Themen 7
M Zahlen als Bytes in eine Datei speichern, daraus wieder auslesen Java Basics - Anfänger-Themen 2
D Schon wieder double -.- Java Basics - Anfänger-Themen 4
R Switch: Nach durchlaufen des Case wieder zum Menü Java Basics - Anfänger-Themen 3

Ähnliche Java Themen

Neue Themen


Oben