JPanel und Repaint

protectedzone

Aktives Mitglied
Hi

Ich habe zwei JPanels, die sich überlappen, beide sind halbtransparent (oder opaque==false).

Wenn ich eines nun repainte, wird das andere Zwangsläufig auch repainted.

Nun muss es doch eine Möglichkeit geben, dass das untere Panel nicht repainted wird, und trotzdem angezeigt wird.

Es muss doch irgendwie machbar sein, dass das dann "die Grafikkarte übernimmt" und nicht Java!



Mir fällt gerade noch eine Möglichkeit ein, aber die wäre sehr hässlich: Ich erzeuge zwei JFrames, die sich überlappen, und ein JFrame ist (halb-)durchsichtig. In diesem Fall müsste das untere JFrame nicht bei jeder Änderung repainted werden.


Aber es gibt doch sicher eine bessere Lösung!

Grüsse, pZone
 
Ich rufe die überschriebene paintComponent(Graphics g) Methode des unteren Panels auf (asynchron durch repaint())

Java:
@Override
public void paintComponent(Graphics g) {
//...
}

Im Konstruktor des Panels steht:

Java:
this.setOpaque(false);

Dabei wird leider auch die paintComponent-Methode des darüberliegenden Panels aufgerufen.

Das JFrame hat ausserdem ein Null-Layout und es spielt keine Rolle, ob das darüberliegende Panel ein Kind des darunterliegenden Panels ist oder ob sie in keiner Eltern-Kind-Beziehung stehen, das darüberliegende Panel wird immer neu gezeichnet!
 
Ich versteh dein Problem nicht so ganz, bei mir werden auch nach dem neuzeichnen noch beide panel angezeigt

Java:
package panel;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class Foo{

	class RedPanel extends JPanel{
		
		int width = 200;
		int height = 200;
		
		
		public RedPanel(){
			setOpaque(false);
		}
		
		@Override
		public void paintComponent(Graphics g){
			super.paintComponent(g);
			Graphics2D g2 = (Graphics2D) g;
			g2.setColor(new Color(255, 0, 0, 50));		
			g2.fillRect(0, 0, width, height);
		}
	}
	
	class BluePanel extends JPanel{
		
		int width = 200;
		int height = 200;
		
		
		public BluePanel(){}
		
		@Override
		public void paintComponent(Graphics g){
			super.paintComponent(g);
			Graphics2D g2 = (Graphics2D) g;
			g2.setColor(new Color(0, 0, 255, 100));		
			g2.fillRect(0, 0, width, height);
		}
	}
	
	public static void main(String[] args){
		JFrame f = new JFrame();
		f.setLayout(null);
		
		RedPanel rp = new Foo().new RedPanel();
		rp.setBounds(50, 50, 155, 155);

		BluePanel bp = new Foo().new BluePanel();
		bp.setBounds(80, 80, 155, 155);
		
		f.add(rp);
		f.add(bp);
		f.revalidate();
		f.setSize(500,500);
		f.setLocationRelativeTo(null);
		f.setDefaultCloseOperation(2);
		f.setVisible(true);
		
		f.addMouseListener(new MouseListener(){
			
			@Override
			public void mouseReleased(MouseEvent e){}
			
			@Override
			public void mousePressed(MouseEvent e){
				rp.setBounds(0, 0, 250, 250);
				f.revalidate();
			}
			
			@Override
			public void mouseExited(MouseEvent e){}
			
			@Override
			public void mouseEntered(MouseEvent e){}
			
			@Override
			public void mouseClicked(MouseEvent e){}
		});
	}
}

übermalt dein panel der nicht opaque ist den anderen oder wo liegt das konkrete problem ?
 
Zuletzt bearbeitet:
Nein, das Problem lag darin, dass wenn ich das Rote Panel neuzeichnen wollte, dass blaue zwangsläufig auch neu gezeichnet wurde.

Und für mich bedeutet das Overhead, wenn ich nämlich das blaue neuzeichnen muss, obwohl ich nur das rote neuzeichnen möchte.

Probiere sonst mal meine Klasse aus und klicke auf das Frame und liess den Output.

Wenn du das ganze JFrame mit einem x-beliebigen anderen Fenster bedeckst und dann wieder frei machst, werden die Panels ja auch nicht neugezeichnet. Das übernimmt das Betriebssystem und die Graphikkarte.
Und genau das selbe Prinzip wollte ich eigentlich auf das blaue Panel anwenden.


Java:
package panel;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Foo {

    class RedPanel extends JPanel {

        int width = 200;
        int height = 200;

        public RedPanel() {
            setOpaque(false);
        }

        @Override
        public void paintComponent(Graphics g) {
            System.out.println("red");
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;
            g2.setColor(new Color(255, 0, 0, 50));
            g2.fillRect(0, 0, width, height);
        }
    }

    class BluePanel extends JPanel {

        int width = 200;
        int height = 200;

        public BluePanel() {
        }

        @Override
        public void paintComponent(Graphics g) {
            System.out.println("blue");
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;
            g2.setColor(new Color(0, 0, 255, 100));
            g2.fillRect(0, 0, width, height);
        }
    }

    public static void main(String[] args) {
        final JFrame f = new JFrame();
        f.setLayout(null);

        final RedPanel rp = new Foo().new RedPanel();
        rp.setBounds(50, 50, 155, 155);

        final BluePanel bp = new Foo().new BluePanel();
        bp.setBounds(80, 80, 155, 155);

        f.add(rp);
        f.add(bp);
        f.revalidate();
        f.setSize(500, 500);
        f.setLocationRelativeTo(null);
        f.setDefaultCloseOperation(2);
        f.setVisible(true);

        f.addMouseListener(new MouseListener() {

            @Override
            public void mouseReleased(MouseEvent e) {
            }

            @Override
            public void mousePressed(MouseEvent e) {
                System.out.println("---");
                if (Math.random() < 0.5){
                    System.out.println("repaint red");
                    rp.repaint();
                } else {
                    System.out.println("repaint blue");
                    bp.repaint();
                }
            }

            @Override
            public void mouseExited(MouseEvent e) {
            }

            @Override
            public void mouseEntered(MouseEvent e) {
            }

            @Override
            public void mouseClicked(MouseEvent e) {
            }
        });
    }
}
 
Das übernimmt das Betriebssystem und die Graphikkarte.

Das übernimmt das Toolkit und die GraphicsEnvironment....

Wenn du das ganze JFrame mit einem x-beliebigen anderen Fenster bedeckst und dann wieder frei machst, werden die Panels ja auch nicht neugezeichnet.

da sich ihr zustand auch nicht geändert hat, sondern du lediglich einen im z-index höheren Frame / Container darüberlegst, allerdings bin ich mir da nicht so sicher das nicht trotzdem neu gezeichnet wird, müsste ich jetzt ausprobieren.

Optimierst du oder warum geht es dir um den Overhead ? so komplexe Formen das du dermaßen speicherverbrauch hast ? oder einfach nur wenig resourcen zur verfügung ?

ansonsten halt aktiv zeichnen, dann bist du allerdings auch vollkommen selbst für verantwortlich wann du was neu zeichnest.

Code:
blue
red
blue
red
---
repaint red
blue
red
---
repaint blue
blue
---
repaint red
blue
red
---
repaint red
blue
red
---
repaint blue
blue
---
repaint red
blue
red
---
repaint blue
blue
---
repaint red
blue
red
---
repaint red
blue
red
---
repaint blue
blue
---
repaint blue
blue
---
repaint blue
blue
---
repaint red
blue
red
---
repaint red
blue
red
---
repaint blue
blue
---
repaint red
blue
red

du willst also immer nur einen , den von dir ausgewählten panel neu zeichnen und nicht , wie vom toolkit initiiert den gesamten inhalt des frames , ist das soweit korrekt ?
 
Zuletzt bearbeitet:

Zurück
Oben