Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
BufferedImage Teilbereich wieder transparent setzen
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 ;-)).
... 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 ?
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 ?
(...)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. (...)
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.
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: "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.
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 ^^
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?
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 ...
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 ;-)
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:
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.
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*
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.
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 !
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.