Swing Frame mit GlassPane und Popup

Nejah

Mitglied
Hallo miteinander!

Ich habe folgendes vor: In einem JFrame wird ein Popup aufgerufen. Während dieses Popup geöffnet ist, sollen die Elemente im Content Pane nicht aktiviert werden können. Hierfür setze ich das Glass Pane mit den entsprechenden Event-Listenern.

Nun zum Problem: Sobald das Glass Pane auf visible gesetzt wird, sind die Elemente des Popups zwar nutzbar (mit System.out leicht zu überprüfen), jedoch werden offenbar keine Repaints mehr gemacht. Das heißt zum Beispiel für Buttons, dass sie nicht "eingedrückt" werden, wenn man auf sie klickt, oder die Inhalte von JSpinnern nicht aktualisiert werden. Auch sämtliche Hover-Events sind nicht mehr zu sehen.

Ich habe das Problem mal auf die nötigsten Zeilen heruntergebrochen, damit ihr euch selbst ein Bild machen könnt:

Java:
public class PopupGlassPaneTest
{
    public static void main(final String[] args)
    {
        // The frame
        final JFrame frame = new JFrame();
        frame.setSize(800, 600);
        frame.setLayout(new GridLayout(3, 2));

        for (int i = 0; i < 6; i++)
        {
            frame.add(new JButton("Button " + i));
        }

        frame.setVisible(true);

        // The pop-up
        final JButton testButton = new JButton("TEST");
        testButton.addActionListener(new ActionListener()
        {

            @Override
            public void actionPerformed(final ActionEvent e)
            {
                System.out.println("BUTTON PRESSED");
            }

        });

        final JPanel panel = new JPanel();
        panel.add(testButton);

        final Popup popup = PopupFactory.getSharedInstance().getPopup(frame, panel, frame.getX() + 75, frame.getY() + 100);
        popup.show();

        // The glass pane
        final JPanel glassPane = new PopupGlassPaneTest.GlassPane();
        glassPane.setOpaque(false);
        frame.setGlassPane(glassPane);
        glassPane.setVisible(true);
    }

    private static class GlassPane extends JPanel
    {
        @Override
        public void paintComponent(final Graphics g)
        {
            super.paintComponent(g);
            final Color ppColor = new Color(70, 70, 255, 120);
            g.setColor(ppColor);
            g.fillRect(0, 0, this.getWidth(), this.getHeight());
        }
    }
}

Der Button "Test" spuckt hierbei das erwartete System.out aus, man sieht aber nicht, dass man ihn klickt. Hat jemand eine Idee, wieso die entsprechenden Repaints nicht mehr getriggert werden und wie ich sie wieder reinbekomme?

Überhaupt kommt mir die ganze Anzeige komisch vor. Nach meinem Verständnis müsste doch GlassPane auch über LayeredPane (enthält Popups) liegen, was hier aber nicht der Fall ist (Popup liegt über dem GlassPane). Oder vertu' ich mich da?

Ich bin mir übrigens voll bewusst, dass ein modaler Dialog sehr viel einfacher wäre. Geht aber in dem Fall leider nicht, weil soll halt so sein 😉

EDIT: Hab' nochmal schnell einen Screenshot von dem Programm hochgeladen.
 
Zuletzt bearbeitet:
warum willst du eigentlich den weg über das Popup gehen? du kannst ja dein Panel direkt auf den Glasspane legen:

Java:
  JPanel glassPane = (JPanel) frame.getGlassPane();
        glassPane.setLayout(new BorderLayout());

        JPanel ownGlassPane = new GlassPane();
        ownGlassPane.setOpaque(false);

        // The glass pane
        glassPane.add(ownGlassPane, BorderLayout.CENTER);

        final JPanel panel = new JPanel();
        panel.add(testButton);    

        ownGlassPane.add(panel);

        glassPane.setVisible(true);
 
Zuletzt bearbeitet:
Habe noch nie mit Popup gearbeiten und auch keine Erklärung warum das Eindrücken nicht zu sehen ist.
Wenn man ein JPopupMenu verwendet funktioniert es allerdings:
Java:
	final JPopupMenu popup = new JPopupMenu();
	popup.add(panel);
	popup.setLocation(frame.getX() + 75, frame.getY() + 100);
	popup.setVisible(true);

####EDIT####
Würde aber auch eher zu dem Vorschlag von Niki tendieren und das Zeugs direkt auf die GlassPane legen.
 
Zuletzt bearbeitet:
Danke für die Antworten 🙂

Ja, mit dem setVisible kracht's halt leider 🙁

Von wollen kann keine Rede sein. Es ist eher ein Sollen - vorhandenes Framework nutzen und so ...

Rein über das GlassPane wäre aber auch eine überlegenswerte Idee. Muss ich mal schauen, ob das nicht hinterher doch noch zusätzliche Probleme bringt. Spontan fiele mir aber tatsächlich kein Grund ein.

Trotzdem würd's mich schon irgendwo interessieren, wo's da genau hakt. Im Netz bin ich bisher jedenfalls noch nicht fündig geworden.
 
Eine andere Alternative wäre ein modaler undekorierter Dialog. Dann könnte man sich sogar die GlassPane und das Abfangen von Benutzerinteraktionen sparen.
 
Hier jedenfalls mal die Variante rein mit GlassPane, falls es jemand nachbasteln möchte 😉

Java:
public class PopupGlassPaneTest
{
    public static void main(final String[] args)
    {
        // The frame
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setSize(800, 600);
        frame.setLayout(new GridLayout(3, 2));

        for (int i = 0; i < 6; i++)
        {
            frame.add(new JButton("Button " + i));
        }

        frame.setVisible(true);

        // The pop-up
        final JButton testButton = new JButton("TEST");
        testButton.addActionListener(new ActionListener()
        {

            @Override
            public void actionPerformed(final ActionEvent e)
            {
                System.out.println("BUTTON PRESSED");
            }

        });

        final JPanel panel = new JPanel(new GridLayout(1, 1));
        panel.add(testButton);
        panel.setBorder(new EmptyBorder(3, 3, 3, 3));
        panel.setBounds(frame.getX() + 75, frame.getY() + 100, testButton.getPreferredSize().width + 6, testButton.getPreferredSize().height + 6);

        // The glass pane
        final JPanel glassPane = new GlassPane(true);
        glassPane.setLayout(null);
        glassPane.add(panel);
        glassPane.setOpaque(false);
        frame.setGlassPane(glassPane);
        glassPane.setVisible(true);
    }

    private static class GlassPane extends JPanel implements MouseMotionListener, MouseListener
    {
        private static final long serialVersionUID = 853104957924648368L;

        private final boolean     _isModal;

        public GlassPane(final boolean isModal)
        {
            this._isModal = isModal;
            this.setOpaque(false);

            if (isModal)
            {
                this.addMouseListener(this);
                this.addMouseMotionListener(this);
            }
        }

        @Override
        public void paintComponent(final Graphics g)
        {
            super.paintComponent(g);

            if (this._isModal)
            {
                final Color ppColor = new Color(70, 70, 255, 120);
                g.setColor(ppColor);
                g.fillRect(0, 0, this.getWidth(), this.getHeight());
            }
        }

        @Override
        public void mouseClicked(final MouseEvent e)
        {
        }

        @Override
        public void mousePressed(final MouseEvent e)
        {
        }

        @Override
        public void mouseReleased(final MouseEvent e)
        {
        }

        @Override
        public void mouseEntered(final MouseEvent e)
        {
        }

        @Override
        public void mouseExited(final MouseEvent e)
        {
        }

        @Override
        public void mouseDragged(final MouseEvent e)
        {
        }

        @Override
        public void mouseMoved(final MouseEvent e)
        {
        }
    }
}
 

Zurück
Oben