views:

82

answers:

2

The application I'm working on contains a main JFrame, from which users might eventually open another supplementary frame. I am trying to implement such a behavior of the app where the supplementary frame is minimized (iconified) as soon as the main frame gets minimized.

I was thinking of overriding the setExtendedState method of the main frame to capture the moment when it gets minimised, and then fire property change event from there so that the supplementary frame may act upon to it.

I discovered however, that unfortunately the overridden setExtendedState never gets called.

I would greatly appreciate any ideas of achieving the desired behavior. Below is the code I used for testing...

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

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


public class IconifySupplementaryFrameTest {

    public static void main(String[] args) {
        (new MainFrame()).setVisible(true);
    }

}

class MainFrame extends JFrame {
    public static final String EXTENDED_STATE_KEY = "extendedState";

    MainFrame() {
        super("Iconify test - main window");

        setLayout(new FlowLayout(FlowLayout.LEADING));

        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(400, 400);
        setLocationByPlatform(true);

        add(new JButton(new AbstractAction("Show supplementary frame") {
            @Override
            public void actionPerformed(ActionEvent e) {
                SupplementaryFrame.doShow(MainFrame.this);
            }
        }));
    }

    @Override
    public synchronized void setExtendedState(int state) {
// This overridden method is never called ???       
        int oldState = getExtendedState();
        super.setExtendedState(state);
        firePropertyChange(EXTENDED_STATE_KEY, oldState, state);
    }
}


class SupplementaryFrame extends JFrame implements PropertyChangeListener {
    private static SupplementaryFrame instance;

    private SupplementaryFrame(final JFrame parentFrame) {
        super("Iconify test - supplementary window");

        setSize(300, 300);
        setLocationRelativeTo(parentFrame);

        parentFrame.addPropertyChangeListener(
                MainFrame.EXTENDED_STATE_KEY, this);

        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                instance = null;
                parentFrame.removePropertyChangeListener(
                        MainFrame.EXTENDED_STATE_KEY,
                        SupplementaryFrame.this);
                SupplementaryFrame.this.dispose();
            }
        });
    }


    static void doShow(JFrame parentFrame) {
        if(instance == null) {
            instance = new SupplementaryFrame(parentFrame);
            instance.setVisible(true);
        }
        else {
            // omitted _ugly_ code to bring this window (instance) to front 
        }

    }


    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        int state = this.getExtendedState();
        int parentState = ((Integer)evt.getNewValue()).intValue();

        if((parentState & ICONIFIED) == ICONIFIED) 
            this.setExtendedState(state | ICONIFIED);
    }
}
A: 

The application I'm working on contains a main JFrame, from which users might eventually open another supplementary frame

Applications are generally designed to use a single JFrame. Supplementary windows are created by using a JDialog. When you create the dialog make sure you specify the frame as the owner of the dialog. Now when you iconify/deiconify the frame, the dialog is iconified in sync automatically.

camickr
Thanks. I tried that, but then the supplementary window always stays on top of the main frame (even if I setAlwaysOnTop(false);), is not visible on the taskbar and cannot be minimized/maximized by itself.
Dmitry Letano
+1  A: 

Just add WindowStateListener to MainFrame to make your code work with property change listener:

addWindowStateListener(new WindowStateListener() {

        @Override
        public void windowStateChanged(WindowEvent e) {
                firePropertyChange(EXTENDED_STATE_KEY, e.getOldState(), e.getNewState());
        }
    });
YoK
That did the trick, thanks!
Dmitry Letano
As a matter of fact, it seems to be more appropriate to add the WindowStateListener to the supplementary frame. Then there will be no need to add any funciotality to the main frame to achieve the desired behavior.
Dmitry Letano