0

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?

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
DSlomer64
  • 4,234
  • 4
  • 53
  • 88
  • 2
    For better help sooner, post an [MCVE](http://stackoverflow.com/help/mcve) (Minimal Complete and Verifiable Example). See also [this MCVE](http://stackoverflow.com/a/10986504/418556). – Andrew Thompson Apr 20 '14 at 01:32
  • I know, @AndrewThompson, I was hoping to keep it short since the question seemed cut-and-dried. And if I hadn't just figured out how to get at the JMenuBar, I'd post an MCVE. I may just figure out the whole thing, which would be best for me. (BTW, I found an "Answer" of yours earlier and it led me to read with great interest your "Why CS teachers should stop teaching Java applets".) – DSlomer64 Apr 20 '14 at 01:46
  • OH, @AndrewThompson, I had NOT seen the link. THANKS! I'll study it. – DSlomer64 Apr 20 '14 at 02:29
  • @AndrewThompson--the link took me to another place I've been wondering about lately, so I guess you saved me asking that question, although I guess this question closely parallels it. Again, thanks. – DSlomer64 Apr 20 '14 at 02:33
  • 1
    Concerning your deleted answer: Post a new question "How to enumerate the items of a JMenuBar". I don't have my code with me where I did it. I recall there were more special cases. Maybe [getSubElements](http://docs.oracle.com/javase/7/docs/api/javax/swing/JMenuBar.html#getSubElements%28%29) would do? I'd also start with `gameBoard.enableEverything(gameBoard)` instead of the two calls (in order to keep it simple). – maaartinus Apr 20 '14 at 12:34
  • @maaatrinus--Thanks, I'm feeling my way here, really unsure of both the coding and etiquette--just passing `gameBoard` to `enableEverything` for ONE call is pretty obvious now that you've said it! It did what both other approaches did, but, while it still isn't enabling the text area or menu items, it is tidier and a far better solution. As requested, I'll post a new question. I never know when that's appropriate, since it kind of leaves a thread in limbo, with only partially solving original problem and no link to the rest. However, this thread seems pronounced dead, so, will do. – DSlomer64 Apr 21 '14 at 10:49
  • 1
    -1 for not showing a SSCCE (old acronym for the beast @AndrewThompson was suggesting ;-) - something wrong in the code you are not showing – kleopatra Apr 21 '14 at 13:22

4 Answers4

2

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.

maaartinus
  • 44,714
  • 32
  • 161
  • 320
  • A recursive call... I like it! – DSlomer64 Apr 20 '14 at 01:49
  • 1
    Just checking you saw the edit to my comment. It included a link to an example. – Andrew Thompson Apr 20 '14 at 01:56
  • 1
    @DSlomer64: And in case you wouldn't like recursion, you could use a stack (`List`) or `Queue` to simulate it. This would give you control over the processing order. – maaartinus Apr 20 '14 at 01:57
  • @AndrewThompson: No, I didn't see your comment before. But I recognize you were faster than me. – maaartinus Apr 20 '14 at 02:04
  • Sorry, I should have made it clear I was talking to the OP. I figure you don't need an example of doing what you said. ;) Oh, and thanks for the reminder, I'd forgotten to up-vote. :) – Andrew Thompson Apr 20 '14 at 02:08
  • @AndrewThompson: I wasn't sure what you meant. Thank you. – maaartinus Apr 20 '14 at 12:27
  • @Andrew Thompson: Thanks for pointing out my errors in judgement and etiquette and properly editing my original post. I'd gladly delete as requested, but it's locked and advises to flag "for moderator attention", which I did, though I wasn't sure I should, since it's already attracted much moderator attention. – DSlomer64 Apr 21 '14 at 11:07
1

"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.

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • I had already figured out one part of what you replied with, but not the others, so thanks a heap. Or a stack. Whichever. – DSlomer64 Apr 20 '14 at 02:34
  • @peeskillet--I tried and tried to use `getJMenuBar()` to do the enabling but I couldn't even get compilation, let alone figure out how to apply recursion. If you find the time, I'd sure like to see what you suggested. Meanwhile, I found a way to enable the menu items, though it's not what I'd call slick code. – DSlomer64 Apr 21 '14 at 12:53
  • 1
    Post an example with all your menu and menu items in place and point out exactly what it is you are trying to acheive – Paul Samsotha Apr 21 '14 at 12:55
  • @peeskillet--@kleopatra put this into perspective--it's not how to run a railroad, [dis|en]abling menu items this way. The code in "Answer" "Here's what worked" below got me through the menu items; everything got enabled; **academic pursuit completed; nothing practical accomplished**. I won't bother y'all with this any further. I'll wait until some actual coding problem rears its head and stumps me in the context of developing the nuts and bolts of this program and will then post an MCVE. – DSlomer64 Apr 21 '14 at 18:38
  • @peeskillet--P.S. I was just looking for a way to access EVERY component from JFrame down to JMenuItem with one recursive procedure. Couldn't; but found a second hunk of code to do so. And kleopatra suggests it's possible to do so and suggests finding error in my code, which I may tackle soon. – DSlomer64 Apr 21 '14 at 18:41
0

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.

DSlomer64
  • 4,234
  • 4
  • 53
  • 88
  • 1
    there is nothing special regarding menuItems - technically you walk the container hierarchy recursively just the same as any other container hierarchy. If that's not working for some reason, there's an error in your code somewhere. On the other hand, it's wrong to enable/disable a menuItem - instead, use actions and enable/disable those actions. – kleopatra Apr 21 '14 at 13:19
0

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.

Community
  • 1
  • 1
DSlomer64
  • 4,234
  • 4
  • 53
  • 88
  • `((JScrollPane) c).getViewport()).getView()` does the job. – maaartinus Oct 18 '14 at 22:03
  • @maaartinus--`getView` "Returns the JViewport's one child or null." I have `Component s; s = (((JScrollPane)cc).getViewport()).getView();` but how do I set tool tips off? I tried `s.setTooltips...` but got error--setTooltips isn't valid in context. – DSlomer64 Oct 20 '14 at 22:48
  • 1
    The returned `Component` may be anything. If it's `Container`, you simply pass it to `tipsOff`. If it's a `JComponent`, then call `setToolTipText`. It may obviously be both as `JComponent extends Container`. If it's neither, then probably there's nothing to do, but print `s.getClass()` to find out more. – maaartinus Oct 21 '14 at 00:20
  • 1
    Or much simpler: `(JScrollPane)cc).getViewport()` is a `JComponent`, therefore also `Container`, so feed it to `tipsOff` and you're done. – maaartinus Oct 21 '14 at 00:22
  • 1
    Related: [Storing default values of JComponent Attributes](http://stackoverflow.com/questions/26166430/is-it-possible-to-invert-all-booleans-within-a-java-class/26166706#26166706) For component-level features like isVisible or isEnabled, you can save and re-instantiate attribute states to an initialzied state (i.e. a text field is disabled until a checkbox is checked). – Compass Oct 22 '14 at 15:51
  • @Compass--Thanks for the link! I'm going to have to study it. I'm new to hash maps--that's the main problem. But your post reads well enough that I'm on it. – DSlomer64 Oct 22 '14 at 22:33