4

There is a bean property "visible", which is represented by getter isVisible() and setter setVisible() in class Window.

How to listen for this value?

I would like to implement popular "view" menu with check box with binding library. Unfortunately I can't see how to bind "visible" property of a window. Even I can't write translator, because I see no any predefined way to listen for this property:

package tests;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.event.WindowStateListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

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

    public class Try_Swing2 {

        public static void main(String[] args) {

            SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {


                    final JFrame frame2 = new JFrame();
                    frame2.addWindowStateListener(new WindowStateListener() {

                        @Override
                        public void windowStateChanged(WindowEvent e) {

                            System.out.println("windowState.newState = " + e.getNewState());


                        }
                    });

                    frame2.addWindowListener(new WindowListener() {

                        @Override
                        public void windowOpened(WindowEvent e) {
                            System.out.println("windowOpened");
                        }

                        @Override
                        public void windowIconified(WindowEvent e) {
                            System.out.println("windowIconified");

                        }

                        @Override
                        public void windowDeiconified(WindowEvent e) {
                            System.out.println("windowDeiconified");

                        }

                        @Override
                        public void windowDeactivated(WindowEvent e) {
                            System.out.println("windowDeactivated");
                        }

                        @Override
                        public void windowClosing(WindowEvent e) {
                            System.out.println("windowClosing");
                        }

                        @Override
                        public void windowClosed(WindowEvent e) {
                            System.out.println("windowClosed");
                        }

                        @Override
                        public void windowActivated(WindowEvent e) {
                            System.out.println("windowActivated");
                        }
                    });

                    frame2.addPropertyChangeListener("visible", new PropertyChangeListener() {

                        @Override
                        public void propertyChange(PropertyChangeEvent evt) {
                            System.out.println("visible = " + evt.getNewValue());
                        }
                    });

                    frame2.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);

                    frame2.setTitle("This window is controlled by another window");

                    frame2.setSize(800, 600);
                    frame2.setLocationRelativeTo(null);
                    frame2.setVisible(true);

                    AbstractAction toggleAction = new AbstractAction("Toggle another window visibility") {

                        @Override
                        public void actionPerformed(ActionEvent e) {
                            frame2.setVisible( !frame2.isVisible() );
                        }

                    };


                    JButton toggleButton = new JButton(toggleAction);

                    JFrame frame1 = new JFrame();

                    frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                    frame1.setTitle("This windows controls");
                    frame1.setLayout(new FlowLayout());
                    frame1.add(toggleButton);


                    frame1.pack();
                    frame1.setLocation(0, 0);
                    frame1.setVisible(true);




                }
            });

        }
    }
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
Suzan Cioc
  • 29,281
  • 63
  • 213
  • 385
  • 1
    _a bean property "visible"_ no, its not a bean property. You'll need an adapter that listens to windowEvents and maps them to a bean property, then bind your client to that adapter – kleopatra Mar 28 '14 at 13:03
  • 3
    You can use a `ComponentListener` and override `componentShown` and `componentHidden`. It's similar in nature – Paul Samsotha Mar 28 '14 at 13:06

3 Answers3

3

The visible property is not really bound to the WindowsListener, but to the ComponentListener because it belong to the Component class, not the Window class.

In order to listen to changes in the visible property, the componentShown(ComponentEvent e) method of the ComponentListener needs to be implemented. It is always easier to inherit from the adapters, so in this case:

frame2.addComponentListener(new ComponentAdapter() {

    @Override
    public void componentShown(ComponentEvent e) {
        System.out.println("Component is Visible");
    }
});

The adapters have empty implementations of the listeners, e.g. ComponentAdapter class which has empty implementations of the methods in ComponentListener, and WindowAdapter from WindowListener.

For more details, see Component Adapter, Component Listener, and How to Write a Component Listener and

bric3
  • 40,072
  • 9
  • 91
  • 111
toto_tico
  • 17,977
  • 9
  • 97
  • 116
2

The method documentation for Component.addPropertyChangeListener clearly lists the properties that are being observed. The visibility state is not listed. And as a JFrame (or one of its super classes up to Component) does not add any new behavior, you cannot observe changes to the visibility state on a JFrame.

However, you could subclass JFrame with overriding the setVisible method. In this new implementation you can fire such a property change:

public class VisibleAwareFrame extends JFrame {
    public void setVisible(boolean b) {
        boolean visible = isVisible();
        super.setVisible(b);
        firePropertyChange("visible", visible, b);
    }
}
Seelenvirtuose
  • 20,273
  • 6
  • 37
  • 66
  • 1
    subclassing is sub-optimal - and won't help if the frame isn't fully under the control of the binding code. Instead, use an adapter (that's my tag line of today ;-) which maps windowEvents to proper bean properties. Also, the firing is incorrect as you can't know if the new visible really is b after calling super - as a general rule, always query for the new property when firing – kleopatra Mar 28 '14 at 13:36
  • What adapters are you speaking all the day? Why are you keeping a secret? – Suzan Cioc Mar 28 '14 at 13:43
  • 1
    @Seelenvirtuose will this react on pressing cross by mouse? – Suzan Cioc Mar 28 '14 at 13:51
  • @kleopatra You are completely right. Was a quick solution, I thought of. SuzanCioc: He told about a WindowAdapter added to a JFrame, whose methods will be called by the windowing system. Such a method call will tell you what happened. – Seelenvirtuose Mar 28 '14 at 19:17
  • the `visible` property is not part of the `Window` class but the [`Component` class](https://docs.oracle.com/javase/8/docs/api/index.html?javax/swing/JFrame.html). Therefore the correct listener to use is `ComponentListener` that has the `componentShown` method. See my answer below. – toto_tico Apr 16 '16 at 20:40
1

Try Global AWT Event Listener

long eventMask = AWTEvent.COMPONENT_EVENT_MASK;

Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
    public void eventDispatched(AWTEvent e) {
        String paramString = e.paramString();
        System.out.println(paramString);
    }
}, eventMask);

Here is the some outputs

COMPONENT_RESIZED (0,0 500x500)
COMPONENT_HIDDEN
COMPONENT_RESIZED (0,0 500x500)
COMPONENT_RESIZED (0,0 500x500)
COMPONENT_RESIZED (4,23 492x473)
COMPONENT_MOVED (4,23 492x473)
COMPONENT_RESIZED (0,0 492x473)
COMPONENT_RESIZED (0,0 500x500)
COMPONENT_MOVED (0,0 500x500)
COMPONENT_SHOWN
COMPONENT_MOVED (0,0 500x500)
COMPONENT_MOVED (0,0 500x500)
COMPONENT_RESIZED (0,0 500x500)
COMPONENT_HIDDEN
COMPONENT_RESIZED (0,0 494x475)
COMPONENT_MOVED (0,0 494x475)

You can put checks on source as well as event type on paramString. Check for COMPONENT_HIDDEN and COMPONENT_SHOWN event and based on event change or set the visible property. It might help you.

Braj
  • 46,415
  • 5
  • 60
  • 76