Unter JPanel liegende Komponenten "totschalten"

  • Themenstarter Themenstarter tuxedo
  • Beginndatum Beginndatum
T

tuxedo

Gast
Hallo zusammen,

wieder mal eine Design-Frage an die Swing-Experten:

Ich habe eine Anwendung welche wahlweise im Fullscreen, als auch im Fenster läuft. Es gibt keine Dialoge oder sonstiges. Läuft alles in einem Fenster.

Wenn die Anwendung jetzt mit etwss beschäftigt ist (z.B. DB initiell befüllen, Dateien lesen, ...), dann möchte ich über das bestehende UI ein halbtransparentes Panel legen, welches eine Ladeanimation, sowie einen Hinweistext anzeigt.

Das Panel hab ich schon. Die halbtransparenz, sowie die Ladeanimation hab ich auch. Passt alles.

In meinem JFrame arbeite ich mit dem Borderlayout. Die eigentliche Anwendung läuft vollständig in einem eigenen Panel (max. Fenstergröße) und liegt in
Code:
Borderlayout.CENTER
. Parallel dazu hab ich nun mein "LoadingPanel", welches ebenfalls im Zentrum des Layout's des Frames liegt:
Java:
            contentPane.setLayout(new BorderLayout());
            contentPane.add(loadingPanel, BorderLayout.CENTER);
            contentPane.add(mainPanel, BorderLayout.CENTER);
            pack();

Soweit so gut.

Wenn das LoadingPanel nicht gebraucht wird, wird es invisible geschalten. Wird es gebraucht, wird es einfach sichtbar gemacht.

Das Problem ist jetzt: Beide Panels liegen an der gleichen Stelle und konkurrieren untereinander. Bewege ich die Maus über einen Button im mainPanel, dann blitzt der Button hervor und überzeichnet das loadingPanel...

Gibt's eine einfache Möglichkeit ein Panel, sowie alle "Child-Components" komplett tot zu stellen, ohne deren eigenen Eigenschaften (focusable/visible/...) nachhaltig zu verändern? Könnte über alle Components des mainPanels iterieren und überall "focusable" etc. abschalten. Aber beim zurückstellen müsste ich mir ja vorher noch gemerkt haben wie der "zuvor" Zustand war um diesen wiederherzustellen. Gibt's nicht was einfaches?

- Alex
 
Für sowas kannst du das GlassPane des Fensters verwenden. Darauf das Lade-Panel legen. Das catcht automatisch die Events.

Java:
import java.awt.Color;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GlassPaneExample {
	private JFrame glassPaneFrame;
	
	public GlassPaneExample() {
		createGlassPaneFrame();
		createGlassPaneControllFrame();
	}
	private void createGlassPaneControllFrame() {
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		frame.add(new JButton(new AbstractAction("Show/Hide glass pane") {
			public void actionPerformed(ActionEvent e) {
				glassPaneFrame.getGlassPane().setVisible(!glassPaneFrame.getGlassPane().isVisible());
			}
		}));
		
		frame.pack();
		frame.setVisible(true);
	}
	private void createGlassPaneFrame() {
		glassPaneFrame = new JFrame();
		glassPaneFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		glassPaneFrame.add(new JButton("Some"));
		
		JPanel glassPane = new JPanel();
		
		glassPane.setBackground(new Color(255, 0, 0, 127));
		glassPaneFrame.setGlassPane(glassPane);
		
		glassPaneFrame.pack();
		glassPaneFrame.setLocationRelativeTo(null);
		glassPaneFrame.setVisible(true);
	}
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				new GlassPaneExample();				
			}
		});
	}
}
 
Okay, das mit kom konkurrierenden Zeichnen hat sich damit erledigt. Aber die Events werden nicht abgefangen:

Java:
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GlassPaneExample {

    private JFrame glassPaneFrame;

    public GlassPaneExample() {
        createGlassPaneFrame();
        createGlassPaneControllFrame();
    }

    private void createGlassPaneControllFrame() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(new JButton(new AbstractAction("Show/Hide glass pane") {

            public void actionPerformed(ActionEvent e) {
                glassPaneFrame.getGlassPane().setVisible(!glassPaneFrame.getGlassPane().isVisible());
            }
        }));

        frame.pack();
        frame.setVisible(true);
    }

    private void createGlassPaneFrame() {
        glassPaneFrame = new JFrame();
        glassPaneFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JButton button = new JButton("Some");
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("clicked!");
            }
        });
        
        glassPaneFrame.add(button);

        JPanel glassPane = new JPanel();

        glassPane.setBackground(new Color(255, 0, 0, 127));
        glassPaneFrame.setGlassPane(glassPane);

        glassPaneFrame.pack();
        glassPaneFrame.setLocationRelativeTo(null);
        glassPaneFrame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            public void run() {
                new GlassPaneExample();
            }
        });
    }
}

Man kann den Button klicken wenn die GlassPane sichtbar ist.... Auf der Console erscheint "clicked!" ..

Hir steht aber dass das nicht gehen soll: How to Use Root Panes (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Swing Components)

Verwende Oracle java 1.7.0_01 64bit unter Debian Linux 6 amd64 ... Mach ich was falsch?
 
Zuletzt bearbeitet von einem Moderator:
Sry, mein Fehler. Durch die Farbe sah es so aus, als würden Events abgefangen werden. Wenn du am GlassPane einen MouseListener registrierst, sollte es richtig funktionieren:

Java:
glassPane.addMouseListener(new MouseAdapter() {});
 
Ah, okay. Jetzt geht's. Muss man auch erstmal wissen dass man, wenn man keinen MouseListener registriert, per default alle Events durchgereicht werden. Hätte jetzt erwartet dass man, wenn eine GlassPane gesetzt ist, sich selbst um's durchreichen kümmern muss.

- Alex
 

Zurück
Oben