Question

Partly for learning purposes, I made a JFrame with 4 JPanels, 2 JLabels, and a JMenuBar. I put various components (buttons, textboxes, textarea) into the 4 JPanels. I disabled every one of the components throughout.

I then wrote two methods to try to enable everything. Worked partially. Here's the code:

  public void enableEverything(){
    Component [] p = this.getContentPane().getComponents();
    for(Component pp : p)
      if(pp instanceof JPanel)
        enableAll((JPanel) pp);
  }

  public void enableAll(JPanel p){
    Component [] c = p.getComponents();
    for(Component cc: c)
      cc.setEnabled(true);
    jTextArea1.setEnabled(true);
    jScrollPane1.setEnabled(true);
  }

The JTextArea (inside a JScrollPane) didn't get enabled even with the last two lines above. Why?

I also tried:

Component [] s = jScrollPane1.getComponents();
for(Component ss: s)
  ss.enableInputMethods(true);

How do I enable the textarea?

And the JMenuBar didn't get enabled either. But I really don't know where to find it. I read that it's in the JLayeredPane, but ... what I tried with it didn't work:

for(int i = 0; i < 2; i++){
  System.out.println(i);
  this.getLayeredPane().getComponent(i).setEnabled(true);
}

In which pane do I find the JMenuBar and how would I enable the JMenus? (And even the JMenuItems.)

Of course, this worked:

menFileAndEdit.setEnabled(true);
mnuFile.setEnabled(true);
mnuEdit.setEnabled(true);
mniFileSave.setEnabled(true);
mniEditUndo.setEnabled(true);
mniEditRedo.setEnabled(true);

Keep in mind that I'm just experimenting, trying to learn where everything is and how to access it programmatically by drilling down from the top JFrame using something like getComponents().

1st Edit

Here's how to get at the menu bar!

Component[] m = this.getJMenuBar().getComponents();
    for(Component mm: m)
      mm.setEnabled(true);

2nd Edit

See below for recursive partial solution.

This is a "recursive response" to @maaartinus (though I only just this second read his note about a stack). It's not an answer to my problem, but it's progress.

  public void enableEverything(Container c){
    Component [] p = c.getComponents();
    System.out.println("Component count " + c.getComponentCount() + " for " +   
                                            c.toString().substring(0,40)  );
    for(Component pp : p){
        pp.setEnabled(true);
        if(pp instanceof Container){
          System.out.println("Recursive call for " + pp.toString().substring(0,40));
          enableEverything((Container) pp);
        }
        else System.out.println("No recursive call");
    }

I had to call it twice to get almost everything enabled:

  gameBoard.enableEverything(gameBoard.getContentPane());
  gameBoard.enableEverything(gameBoard.getJMenuBar());

It did away with one method since it's recursive, and it produced same results in that it also did NOT enable the JMenuItems or the JTextArea.

So I'm still looking for how to do that.

It produced interesting output in that every component seems to be an instance of Container, which doesn't seem right:

 gameBoard.enableEverything(gameBoard.getContentPane())
Component count 6 for javax.swing.JPanel[null.contentPane,0,23
Recursive call for    javax.swing.JPanel[pnlGameGrid,12,139,59
Component count 1 for javax.swing.JPanel[pnlGameGrid,12,139,59
Recursive call for    javax.swing.JTextField[jTextField1,233,1
Component count 0 for javax.swing.JTextField[jTextField1,233,1
Recursive call for    javax.swing.JPanel[pnlAvailableLetters,1
Component count 1 for javax.swing.JPanel[pnlAvailableLetters,1
Recursive call for    javax.swing.JToggleButton[jToggleButton1
Component count 0 for javax.swing.JToggleButton[jToggleButton1
Recursive call for    javax.swing.JLabel[lblAvailableLetters,1
Component count 0 for javax.swing.JLabel[lblAvailableLetters,1
Recursive call for    javax.swing.JPanel[pnlScore,476,25,107x9
Component count 2 for javax.swing.JPanel[pnlScore,476,25,107x9
Recursive call for    javax.swing.JTextField[txtScore,21,14,66
Component count 0 for javax.swing.JTextField[txtScore,21,14,66
Recursive call for    javax.swing.JButton[btnScore,21,61,66x24
Component count 0 for javax.swing.JButton[btnScore,21,61,66x24
Recursive call for    javax.swing.JPanel[pnlPlays,624,51,271x5
Component count 3 for javax.swing.JPanel[pnlPlays,624,51,271x5
Recursive call for    javax.swing.JScrollPane[jScrollPane1,13,
Component count 3 for javax.swing.JScrollPane[jScrollPane1,13,
Recursive call for    javax.swing.JViewport[,1,1,220x80,layout
Component count 1 for javax.swing.JViewport[,1,1,220x80,layout
Recursive call for    javax.swing.JTextArea[jTextArea1,0,0,220
Component count 0 for javax.swing.JTextArea[jTextArea1,0,0,220
Recursive call for    javax.swing.JScrollPane$ScrollBar[,0,0,0
Component count 2 for javax.swing.JScrollPane$ScrollBar[,0,0,0
Recursive call for    javax.swing.plaf.metal.MetalScrollButton
Component count 0 for javax.swing.plaf.metal.MetalScrollButton
Recursive call for    javax.swing.plaf.metal.MetalScrollButton
Component count 0 for javax.swing.plaf.metal.MetalScrollButton
Recursive call for    javax.swing.JScrollPane$ScrollBar[,0,0,0
Component count 2 for javax.swing.JScrollPane$ScrollBar[,0,0,0
Recursive call for    javax.swing.plaf.metal.MetalScrollButton
Component count 0 for javax.swing.plaf.metal.MetalScrollButton
Recursive call for    javax.swing.plaf.metal.MetalScrollButton
Component count 0 for javax.swing.plaf.metal.MetalScrollButton
Recursive call for    javax.swing.JButton[jButton1,61,262,81x2
Component count 0 for javax.swing.JButton[jButton1,61,262,81x2
Recursive call for    javax.swing.JCheckBox[jCheckBox1,49,207,
Component count 0 for javax.swing.JCheckBox[jCheckBox1,49,207,
Recursive call for    javax.swing.JLabel[lblPlays,624,29,100x1
Component count 0 for javax.swing.JLabel[lblPlays,624,29,100x1


gameBoard.enableEverything(gameBoard.getJMenuBar())
Component count 2 for javax.swing.JMenuBar[menFileAndEdit,0,0,
Recursive call for    javax.swing.JMenu[mnuFile,0,0,31x21,alig
Component count 0 for javax.swing.JMenu[mnuFile,0,0,31x21,alig
Recursive call for    javax.swing.JMenu[mnuEdit,31,0,33x21,ali
Component count 0 for javax.swing.JMenu[mnuEdit,31,0,33x21,ali

I was hoping recursion would get at the JMenuItems, but no such luck. Any thoughts on how to do so?

Was it helpful?

Solution 4

Six months later, I have a decent, not-altogether-inelegant way to access everything that I needed to below main JFrame, in the context of a menu option action that sets all tool tips to "":

private void tipsOff(Container container)
{
  Component [] c = container.getComponents();
  Component s;
  for (Component cc : c) {
    ((JComponent)cc).setToolTipText("");
    if(cc instanceof JPanel)      tipsOff((Container) cc);
    if(cc instanceof JScrollPane) tipsOff(((JScrollPane)cc).getViewport());
  }
}  

private void mniPrefTooltipsActionPerformed(java.awt.event.ActionEvent evt)
{                                                
  tipsOff(gui.getContentPane());
  tipsOff(gui.mbrMenuBar);
}     

Note recursive call to tipsOff.

Also note comments and Answer about using ToolTipManager (in this thread, which works in the context of my original question to reduce all the code to one line. Point here is that any other operation could be applied instead of ""-ing tool tips--e.g., setting invisible or disabling... etc.

Thanks to maaartinus for the JScrollPane line in tipsOff.

OTHER TIPS

I guess you need to recurse the whole tree, something like

  • start with the root
  • iterate all components
  • enable each of them
  • test if it's an instance of Container
  • if so, do a recursive call

For the ScrollPane you'll probably need an additional instanceof test and then getViewPort or something like this.

"In which pane do I find the JMenuBar and how would I enable the JMenus? (And even the JMenuItems."

The Root Pane of the JFrame holds the JMenuBar.

JFrame.getRootPane().getJMenuBar();

Of course you can always just call JFrame.getJMenuBar(), without having to access the root pane.

To get the menus of the menu bar, you can can JMenuBar.getSubElements which return the MenuElement[]. JMenu Also has getSubElements. Keep in mind though that a MenuELement can be JMenu or a JMenuItem, and a JMenu can have more layers of JMenus. So you will have to do some recursive calling if you wanted to try to access them this way.

As for trying to access specific component types, check if (obj instanceof SomeComponentType) will help you in what you are trying to achieve.

Here's what worked.

  for(int i = 0; i < menFileAndEdit.getMenuCount(); i++){

      menFileAndEdit.getMenu(i).setEnabled(true);

      Component [] cc = menFileAndEdit.getMenu(i).getMenuComponents();

      for(Component c : cc)

          c.setEnabled(true);
  }

That enables each JMenuItem in JMenu menFileAndEdit in the JMenuBar for the form.

That was a lot harder than expected, given the relative ease with which every other element was enabled by recursion using the method in the second edit of the original post. So I wonder if there's a way to use the recursive method to accomplish this.

I also wonder if there's a way to use a collection-based for loop. I tried a couple of things but they wouldn't compile.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top