1

Problem

I have a multi frame environment. Each JFrame has several JComponents, nested in each other. I need to access a global variable of the frame from within some of the embedded components. I can't use static because the static would of course apply to all frames. I can't hand over the frame or a class with the relevant information to all the components (combobox, label, etc).

Current Solution

My current solution is to use a HierarchyListener and once the showing method fires I get access to the JFrame using SwingUtilities.getAncestorOfClass.

Question

Does anyone know of a better solution to get access to a JFrame's attributes from deep inside a component hierarchy? Basically a frame context that all JComponents have access to, but limited to the parent frame. Is there some way using e. g. the EventQueue for that or other indicators?

Code

Here's a MCVE of the current state:

  • 2 frames
  • a panel embedded in a frame
  • panel has a label
  • label is set to the frame's title

The code:

public class MyFrame extends JFrame {

    /**
     * Panel with a label which accesses the parent frame's attributes
     */
    public class MyPanel extends JPanel {

        public MyPanel() {

            // set layout and add the label
            setLayout(new FlowLayout());
            final JLabel label = new JLabel("Placeholder");
            add(label);

            // JFrame is null here, can't use this:
            //   JFrame frame = (JFrame) SwingUtilities.getAncestorOfClass(JFrame.class, this);
            //   label.setText(frame.getTitle());

            // but frame can be accessed once the panel got added using a HierarchyListener 
            addHierarchyListener(new HierarchyListener() {

                @Override
                public void hierarchyChanged(HierarchyEvent e) {
                    long flags = e.getChangeFlags();
                    if ((flags & HierarchyEvent.SHOWING_CHANGED) == HierarchyEvent.SHOWING_CHANGED) {

                        // get frame, get title and set title in label
                        JFrame frame = (JFrame) SwingUtilities.getAncestorOfClass(JFrame.class, MyPanel.this);
                        label.setText(frame.getTitle());

                    }
                }
            });
        }
    }

    /**
     * Frame with title which will be used as example about how to access
     * the frame's attributes from a child component
     */
    public MyFrame(String title, int x, int y) {

        // create content panel
        getContentPane().setLayout(new BorderLayout());
        getContentPane().add(new MyPanel(), BorderLayout.CENTER);

        // frame specific code
        setTitle(title);
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setSize(100, 100);
        setLocation(x, y);
        pack();
        setVisible(true);
    }

    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {

                JFrame frame1 = new MyFrame("Frame 1", 100, 100);
                JFrame frame2 = new MyFrame("Frame 2", 300, 100);

            }

        });
    }
}
Roland
  • 18,114
  • 12
  • 62
  • 93
  • 1) See [The Use of Multiple JFrames, Good/Bad Practice?](http://stackoverflow.com/q/9554636/418556) 2) Don't extend components (or windows), just use instances of them. (Unless in the rare case of changing the existing functionality of the component, which does not seem to happen in this code.) – Andrew Thompson Jan 27 '18 at 11:50
  • @AndrewThompson The problem is the same with MDI. Besides the code is just a MCVE – Roland Jan 27 '18 at 12:44

0 Answers0