Menu

menu bar height reported to be zero

Help
John B.
2009-04-14
2013-05-23
  • John B.

    John B. - 2009-04-14

    My BFrame is called parent.  If I call parent.getMenuBar().getBounds().height it returns zero unless I pack, setBounds, and then pack again.  Then it returns a height that may actually be the height of the menu (21 in my case).  But then I have to setBounds again after retrieving the height to get my window the size I want it, after which the height is reported as zero again.

    Is this a bug, or am I perhaps doing something wrong?

    I am using the menu height is to aid in calculating the visible height within the window.  I'm subtracting the insets and menu height from the BFrame height.  Let me know if there is a better way to get the menu height, or the dimensions of the visible area in the window.

    This may relate to the problem described in the thread https://sourceforge.net/forum/forum.php?thread_id=3091176&forum_id=287977   Speaking of which, should i post that as a bug in the tracker?

    Thank you.

    - John

     
    • John B.

      John B. - 2009-04-14

      Okay, on second look it appears to have nothing to do with the pack and setBounds calls.  Instead, it varies per run of the program.  Every time or two it will return 21 instead of zero.  It is random, so I'm thinking maybe there is a threading problem somewhere.  My program is single threaded so far so i think it's on the Buoy side.

      Incidentally I'm running into the problem in the constructor of a heavily modified version of the ProcedureEditor class from AoI.  I posted the file at:
      http://sites.google.com/site/johnburak/Home/ProcedureEditor.java

      Towards the end of the constructor I have this code (the system.out.println is for testing this bug):

      // Set size and position of window
      // Make it 90% the height/width of the screen, and centered.
      double screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
      double screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
      double windowWidth = screenWidth * 0.9;
      double windowHeight = screenHeight * 0.9;
      double xOffset = (screenWidth - windowWidth) / 2;
      double yOffset = (screenHeight - windowHeight) / 2;
      parent.pack();//Necessary at time of writing before setBounds() to workaround a bug.
      parent.setBounds(new java.awt.Rectangle((int) xOffset, (int) yOffset, (int) windowWidth, (int) windowHeight));
      int menuHeight = parent.getMenuBar().getBounds().height;
             
      // Set the canvas size
      int viewableWidth = (int)( parent.getBounds().width
              - parent.getComponent().getInsets().left
              - parent.getComponent().getInsets().right );
      int viewableHeight = (int)( parent.getBounds().height
              - parent.getComponent().getInsets().top
              - parent.getComponent().getInsets().bottom
              - menuHeight);
      System.out.println(menuHeight);
      canvasSize = new Dimension( viewableWidth, viewableHeight);   

      Any ideas would be very helpful!  Thank you.

      - John

       
      • francois guillet

        I don't understand what you're trying to achieve, or rather why you can't do it the usual way.

        If you want a precise size for the viewing area of a window, work with the content widget. Use WidgetContainerPanel or CustomWidget. Use methods and/or subclass it to define minimum size / preferred size. Keep in mind, though, that users expect a standard window behaviour (like a resizable window being, well, resizable). If you're more specific, maybe we could provide a better advice. But I think hacking through sizes as you do rather than rely on buoy internals for packing given widget characteristics (min size, pref. size) is not the good way.

        Francois.

         
    • John B.

      John B. - 2009-04-14

      The problem with setting the size of the content and then letting the window fit to that is that then I ca not set the window size explicitly, which I really would like to do.  I am setting the window to be 90% of the screen size and centered on screen.  And I am using a scroll pane for the content so I can have scroll bars later on.  And some of the drawing I'm doing in the scroll pane depends on viewable area size.

      I just found out that if I use getBounds() or getViewSize() of the scroll pane they return zero about half the times I run the program.  Any ideas?

      Ultimately I need a working way to explicitly set the window size and determine the resulting viewable area size.  So far the obvious ways return zero half the runs of the program :(

      Thank you very much for your time and patience.

      -John

       
    • John B.

      John B. - 2009-04-14

      Oops, I should have said that I'm using a ScrollPane in the center of a border container in the window.  The border container is the window's actual content.  Neither the container nor the scroll pane consistently return the viewable size.  Both sometimes return zero.  And it's not always zero it sometimes is -17 (and probably any other number depending on what's in memory?).

      Bear with me, this is my first time using Buoy and my first complicated GUI project.  Thanks everyone!

       
      • francois guillet

        Do not focus on the actual window content size unless you have a good reason to do so. Set the size of what's within the scrollpane. If the user resizes the window and it gets too small, the scrollbars will activate as needed. You need to set the size of the content of the BScrollPane, whatever it is (ie CustomWidget, whatever).

        "The problem with setting the size of the content and then letting the window
        fit to that is that then I ca not set the window size explicitly, which I really
        would like to do" Well I like UI design to tell me how big the window should be rather than have to guess what it should be. It makes life easier. The real question is maybe what size should the panel inside the BScrollPane be. The rest is of little interest, unless there are specific aspects to your UI.

        Francois.

         
    • Peter Eastman

      Peter Eastman - 2009-04-14

      I bet this code is being executed on your application's main thread?  That would explain the threading problems you're having.  As soon as you call pack() on the window, the event dispatch thread gets started up, and from that moment on, you must never interact with the UI except from the event dispatch thread.  That's fundamental to how Swing (and hence Buoy) works.

      I'm also not clear what you're trying to accomplish.  If you call setBounds() to make the window take up 90% of the screen, it will automatically calculate the appropriate sizes for everything in the window.

      Peter

       
    • John B.

      John B. - 2009-04-15

      > As soon as you call pack() on the window, the event dispatch
      > thread gets started up, and from that moment on, you must never
      > interact with the UI except from the event dispatch thread.

      That appears to be nearly the problem.  I did some testing, and it appears that getMenuBar().getBounds().height only workds correctly if called by the event dispatcher.  If called from my main thread it returns bad values on some runs regardless of if it's before or after pack() or if I even call pack() at all.

      > I'm also not clear what you're trying to accomplish.

      I am making an editor based on the procedural editor from AoI.  It will have a column of inputs on the left side of the view-port and a column of outputs on the right.  I would like these columns to "float" over what's in the scroll pane and be fixed to the window so they don't scroll like the normal contents.  I also want the user to be able to drag links between then handles of these inputs/outputs and the modules in the window.  Yes, that means that the links will have to be redrawn as or after the scroll bars are dragged.  This is all my way of allowing the user access to the inputs and outputs regardless of where they are scrolled-to, as well as keeping the intuitive columns on the left and right of the window.  I was planning on accomplishing the "floating" columns in the editor's paint() function, but now I wonder if that's a good idea.

      - John

       
      • Peter Eastman

        Peter Eastman - 2009-04-15

        >If called from my main thread it returns bad values on some runs regardless of if it's before or after pack() or if I even call pack() at all.

        That means you're doing something else even earlier which is causing the event thread to get started up.

        > I would like these columns to "float" over what's in the scroll pane and be fixed to the window so they don't scroll like the normal contents.

        Are you sure that's really what you want?  The outputs in AoI's procedure editor are drawn inside the scroll pane, since you want them to scroll with the rest of the procedure.

        Assuming you really do want them to float on top of the scroll pane, have you considered using an OverlayContainer?

        Peter

         
    • John B.

      John B. - 2009-04-15

      > That means you're doing something else even earlier which is causing
      > the event thread to get started up.

      I'm really not sure where I would have.  Is there an easy way to figure out what calls can start the event handler?  I can search the Buoy source files if I know what function call I'm looking for.  I seem to have my code working well now (fingers crossed).  But it brinks up another question:

      I've switched to a static window size with no scrolling for this project (it's for school and I have only like 2-3 weeks left).  So my main thread set the size of the components and packed the window.  But then I want to center it, which requires getting the window's size in the main thread after a pack (because before packing the window size is returned as zero).  But after pack the event dispatch thread is running, so I'm not supposed to interact with the GUI from my main thread, which includes getting the window dimensions (like getting the menu bar dimensions above).  That makes a catch 22.  And I can't automatically set the window size in an event handler because Buoy events are all user-provided.  Am I missing something?  Window centering in my main thread works but anything that depends on the menu bar size doesn't. :/

      > Assuming you really do want them to float on top of the scroll
      > pane, have you considered using an OverlayContainer?

      Ah, sounds like a good container for this.  Thanks.  If I end up with time to make the window scrollable/resizeable I'll try it.

      Thanks again for all the help.

      - John

       
      • Peter Eastman

        Peter Eastman - 2009-04-15

        The best thing is if you never do any UI manipulation except on the event thread, not even the main thread.  In other words, your main() method simply calls

        EventQueue.invokeLater(new Runnable() {
          public void run()
          {
            createUI();
          }
        });

        Peter

         
    • John B.

      John B. - 2009-04-15

      Oh good.  I'll try that. :)  All of my GUI manipulation is in the ProcedureEditor constructor, so I'll put a call to that in run() above.

      That is a bit ugly code though.  It's AWT so I suppose that makes sense.  I don't like creating anonymous inner classes inside a parameter lists (and just to run a single function).  Perhaps in keeping with the spirit of Buoy, Buoy could wrap that functionality and make it nicer?  Maybe add a invokeLater function to the appropriate class that takes a function name and runs the function in the event thread at the appropriate time.  Let me know if you like the idea and I should put it on the tracker.  Seems like this sort of thing would get used for a lot of programs (any that wants a centered main window, for starters).

      Thanks again!

      - John

       

Log in to post a comment.