Как скрыть всплывающее окно через несколько секунд, если курсор выходит - PullRequest
3 голосов
/ 01 сентября 2011

У меня есть JDialog как всплывающее окно, которое появляется на 3 секунды и удаляется.
Он появляется в позиции курсора и должен располагаться, только если курсор выходит из всплывающего окна.

Если курсор вошел во всплывающее окно, таймер останавливается и запускается снова при выходе.

Но моя первая идея с dispose- Timer, который запускается и останавливается через MouseListener, не работает с некоторыми JComponent s, что вызывает mouseExited().

Моя вторая идея никогда не запустит Таймер

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

Я не хочу добавлять прослушиватель в каждый компонент всплывающего окна.
Есть ли простой способ сделать это.

Пример: * * один тысяча двадцать-одна

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();
        }
    }
}

Ответы [ 2 ]

4 голосов
/ 01 сентября 2011

Начиная с jdk7 вы можете украсить свой контейнер с помощью JLayer и остановить / запустить таймер в его 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()));

Для более старых версий вы можете использовать слой из проекта JXLayer (это был текущий вариант) или перейти к глобальному слушателю, реализующему вручную, как f.i. отображается в глобальных прослушивателях событий

2 голосов
/ 01 сентября 2011

только для примера JButton (и, как я знаю, большинство JComponents) имеет Model

, если вы начнете javax.swing.Timer с модели или с помощью мыши, выведенной из предварительно определенного Rectangle

если мышь возвращается к предопределенному Rectangle, просто перезапустите javax.swing.Timer

Превосходное предложение, так как о JToolTip здесь

...