3 votes

Comment masquer une fenêtre popup après quelques secondes si le curseur sort

Tengo un JDialog comme une fenêtre pop-up qui s'affiche pendant 3 secondes et est supprimée.
Il apparaît à la position du curseur et ne doit être éliminé que si le curseur quitte le popup.

Si le curseur est entré dans la fenêtre pop-up, le minuteur s'arrête et redémarre à la sortie.

Mais ma première idée avec un dispose- Timer qui démarre et s'arrête via MouseListener ne fonctionne pas avec certains JComponent ce qui provoque un mouseExited() .

Ma deuxième idée ne démarrera jamais la minuterie

public void mouseExited( MouseEvent e ) {
    if(!Popup.this.getBounds().contains( e.getLocationOnScreen() )){
        timer.start();
    }
}

Je ne veux pas ajouter le Listener à chaque composant de la popup.
Y a-t-il un moyen facile de le faire ?

Exemple :

public class Popup extends JDialog {

    private static final long serialVersionUID = 1337L;

    private final Timer timer = new Timer( 3000, new ActionListener() {
        @Override
        public void actionPerformed( ActionEvent e ) {
            Popup.this.dispose();
            System.exit( 0 );
        }
    });

    public Popup() {
        setBounds( 100, 100, 300, 300 );
        addMouseListener( new PopupBehavior() );
        getContentPane().setLayout( new BorderLayout() );
        getContentPane().add( new JTextArea(), BorderLayout.NORTH );
        getContentPane().add( new JSplitPane(0,new JPanel(), new JLabel("2")), BorderLayout.CENTER );
        getContentPane().add( new JProgressBar(), BorderLayout.SOUTH );
        getContentPane().add( new JLabel("west"), BorderLayout.WEST );
        getContentPane().add( new JSpinner(), BorderLayout.EAST );
    }

    public static void main( String[] args ) {
        SwingUtilities.invokeLater( new Runnable() {
            @Override
            public void run() {
                new Popup().setVisible( true );
            }
        });
    }

    private class PopupBehavior extends MouseAdapter {
        @Override
        public void mouseEntered( MouseEvent e ) {
            System.out.println("mouseEntered");
            timer.stop();
        }
        @Override
        public void mouseExited( MouseEvent e ) {
            System.out.println("mouseExited");
            timer.start();
        }
    }
}

4voto

kleopatra Points 31585

Depuis jdk7, vous pouvez décorer votre conteneur avec un JLayer et arrêter/démarrer la minuterie dans son processMouseEvent.

class DisposingLayerUI extends LayerUI {

    @Override
    public void installUI(JComponent c) {
        super.installUI(c);
        JLayer jlayer = (JLayer)c;
        jlayer.setLayerEventMask(
                AWTEvent.MOUSE_EVENT_MASK 
        );
    }

    @Override
    public void uninstallUI(JComponent c) {
        JLayer jlayer = (JLayer)c;
        jlayer.setLayerEventMask(0);
        super.uninstallUI(c);
    }

    @Override
    protected void processMouseEvent(MouseEvent e, JLayer l) {
        if (e.getID() == MouseEvent.MOUSE_ENTERED) {
            timer.stop();
        } else if (e.getID() == MouseEvent.MOUSE_EXITED){
            timer.start();

        }
    }

}

// to use in your code, do all init and then decorate the contentPane
...
setContentPane(new JLayer(getContentPane(), new DisposingLayerUI()));

Pour les versions plus anciennes, vous pouvez utiliser le calque de la section JXLayer (c'est là que le courant a été développé) ou opter pour un écouteur global implémenté manuellement, comme par exemple dans le projet Écouteurs d'événements globaux

2voto

mKorbel Points 90340

À titre d'exemple JButton (et comme je sais que la majorité des JComponents ) a Model

si tu commences javax.swing.Timer du Modèle ou de la Moussole, en dehors de ceux qui sont prédéfinis. Rectangle

si la souris revient à la position prédéfinie Rectangle puis redémarrez simplement javax.swing.Timer

Excellente suggestion depuis la création de JToolTip. aquí

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X