Apple menu GUI problems in Java

Discussion in 'Mac Programming' started by Awesomeness, Jan 30, 2010.

  1. Awesomeness macrumors member

    Joined:
    Feb 12, 2009
    #1
    I put in

    Code:
    System.setProperty("apple.laf.useScreenMenuBar", "true");
    to make it so that my menu shows up on the top menu bar instead of inside the frame. However, when I adjust the size of the window, the menu bar inside the frame appears. That's the one I don't want. Also, I'm having trouble enabling/disabling menu items. The bar that appears when I resize the menu has the disabled options I wanted, but the code I use doesn't work on the top menu bar; it just stays enabled.

    Other info:
    The unwanted menu bar inside the frame isn't invisible before I resize it; it doesn't exist. I'll add more if I see some more information that is necessary.
    EDIT: Also, if I resize it without it being manual, as in using setSize() instead, (without clicking on the draggy resize thingy) the menu bar I don't want doesn't show.

    Anyone experienced in Mac GUI have any tips?
     
  2. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #2
    You have to set that property before AWT initializes. Either preset it on command-line, predefine it in app-bundle's Info.plist, or write code in a class that does not cause AWT to load.

    How are you launching your program: command-line, app-bundle, double-clicked jar?

    I don't understand that description. What is the bar that appears when you resize the menu? How are you resizing a menu?

    Can you post a screen shot or a clearer explanation?
     
  3. Awesomeness thread starter macrumors member

    Joined:
    Feb 12, 2009
    #3
    I have the developer kit, and I've used the Jar Bundler before about a year ago, but now I can't find it. Once I make it an application, I can edit the plist. The Java Tools folder isn't in there anymore though, and I searched the whole thing for, "Jar Bundler" and I got nothing! =(

    Here's some screenshots. The first is before resizing, and the second is after, and also shows my problem with menu options disabling in the Mac menu. This application is (eventually) going to be a screen recorder, so the window is slightly transparent, and is called Recordinator.

    EDIT: Also, how do I get rid of the package name, so that it just says Recordinator in the menu instead or recorder.Recordinator?
     

    Attached Files:

  4. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #4
    Which OS version? Which version of dev tools?

    Your screen shot looks like you're using Eclipse.

    If you're using Eclipse, and Ant is your builder, you should probably use this Ant task to create your app-bundle:
    http://informagen.com/JarBundler/

    This assumes you want an app-bundle. If you don't, then say that.

    The menubars are clearly screwed up. It's probably confused AWT by setting the property in your code. As I said before, this won't work unless it's done before AWT initializes.

    Step 1: remove the code that sets the property.

    Step 2: confirm that the in-window menubar works correctly.

    Step 3: post whether your app is a double-clickable jar, an app-bundle, or loose class files.

    The correct course of action is different for app-bundle vs. other forms.

    Again, the correct course of action depends on the answer to Step 3.
     
  5. Awesomeness thread starter macrumors member

    Joined:
    Feb 12, 2009
    #5
    Icon...

    Thanks for the help.

    I've been trying for ages and I've used a million different applications to try and put the image I made in PhotoShop into my application, but they've all screwed up in their own, special, unique way. :mad: Any help? I wish I could just copy the file and paste it into the application's info, but that doesn't work...

    EDIT: I found a solution that doesn't cost a ridiculous amount like 30 bucks! An application (which I have no idea what it's really supposed to do) called Icns2Rsrc that I found online just happens to give this rsrc file that it makes the icon! So I used that! I have no idea what rsrc files are for, lol. I like my icon. I have very low skills in PhotoShop, so I think it's an accomplishment. =D
     

    Attached Files:

  6. Awesomeness thread starter macrumors member

    Joined:
    Feb 12, 2009
    #6
    I'm using a bundle

    And yes, I'm using a bundle.
     
  7. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #7
    OK.

    Followup questions:

    1. Are you using Eclipse to build your app?

    2. How are you building the bundle?

    And questions already asked but still unanswered:

    What OS version?

    What dev tools (Xcode) version?
     
  8. Awesomeness thread starter macrumors member

    Joined:
    Feb 12, 2009
    #8
    1. Yup.

    2. I haven't really yet, instead of using Jar Bundler I've made a folder with all the stuff I need (except for the finished program) like javaApplicationStub and info.plist in it.

    Mac OS X 10.5.7.

    Dev tools 3.0.
     
  9. Awesomeness thread starter macrumors member

    Joined:
    Feb 12, 2009
    #9
    Nevermind, I have found Jar bundler in /usr/share/java/Tools/Jar Bundler.app, without using the Developer kit, and all of my problems disappeared when I made it an application. You were right, I had to put the value in the property list file so that it is changed before awt initializes. Thanks so much!

    EDIT: I have four more problems, two are mandatory to fix and two aren't.

    1. A year ago when I first started using painting in awt, I had problems where the title bar was included in the JFrame size. After what seemed like hours of searching I finally found http://www.acm.org/crossroads/xrds13-3/minueto.html, which saved me. However, I don't want to have a canvas in there because I don't need to paint anything. Plus, the canvas solution won't work because it relies on pack() to work, and I'm going to be resizing all over the place.

    My first idea for a solution would be to figure out the offset created by the current look and feel on each side and use that to find the real size of my window, but I have no idea how to do that.

    2. When I finally find a recording solution, how the user interface will work is that when you record, the box you have below the title bar will be the area that is going to be recorded. However, I need the title bar offset to calculate where the box below really is.

    3. This isn't extremely important, but I'd really like to have a live resize listener; that is instead of the title bar showing the new size once I let go of the mouse, which I have now, it would update the title bar every pixel of change that happens, so it saves users a lot of clicks when they want to make the recording window a certain size.

    4. This isn't super important either, but when I hide my window the menu bar disappears. Apparently apple.laf.useScreenMenuBar only makes the menu bar move to the top when the menu bar is visible. I'd like to be able to hide my window and re-open it whenever I want, because eventually I'll figure out how to make it so that it always stays in front, even when it doesn't have focus.

    I'm sorry that I need so much help... =(

    EDIT #2: I have discovered Frame.getInsets(), which helps me with 1 and 2.
     
  10. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #10
    1 & 2: Size of JFrame content area: Yes, Insets is one way. Another way might be to examine the JFrame's content pane, as it includes any in-window menubar. Or consider using an undecorated JFrame.

    Yet another way is to use a JPanel, instead of a Canvas like the ACM article describes. I have used JPanel as the base class for a drawing surface, and it works fine. Putting a heavyweight Canvas into a lightweight component can cause some difficulties. I don't recall the specifics, but overall I settled on using JPanel.

    3. Live resize listener: Look at ComponentEvent and ComponentListener.

    4. Menubar with closed window: In Java, menubars are tied to windows. It's fundamental to the architecture of AWT and Swing. The way it's usually worked around on Mac OS X is to have an off-screen JFrame with a default menubar, so when all other frames are closed, its menubar becomes active. It's a common technique. Search the archives of Apple's java-dev list (use google, not their on-page search).
    http://lists.apple.com/mailman/listinfo/java-dev
     
  11. Awesomeness thread starter macrumors member

    Joined:
    Feb 12, 2009
    #11
    I already use a ComponentListener. It doesn't trigger the event multiple times as I drag the corner like I want it to; it only triggers the resize event after I let go of the mouse. The appearance I want is that instead of the title showing the new size after I finish resizing and let go of the mouse, it updates the title to show the current size as I drag.

    EDIT: Also, how do I make an offscreen window? Do I just set the location coordinates to something negative or something so that it is never shown?
     
  12. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #12
    You're running OS 10.5.7. That's not the latest version. Maybe the bug you have with resize events is fixed in later updates. Or maybe not. At any rate, this is something you can find out yourself by updating (or reading release notes).

    Maybe try an undecorated JFrame. Again, this is something you can try yourself and see if it changes anything.

    Instead of just firing off multiple "How do I X?" questions, why not try something first, so I don't have to post this Frequently Pasted URL:
    http://WhatHaveYouTried.com/
     
  13. Awesomeness thread starter macrumors member

    Joined:
    Feb 12, 2009
    #13
    I tried updating to 10.5.8, (My dad hasn't bought Snow Leopard) and there's no change... the release notes just said the update was for stability and security.


    I tried using an undecorated JFrame, and it lost the resize corner and the ability to move the window around. I need those.


    Sorry... I'll try to try. :)


    I have tried making an offscreen window, OS X doesn't let me make a window outside of the screen. I did some research, and found http://developer.apple.com/mac/library/releasenotes/CrossPlatform/JavaSnowLeopardUpdate1LeopardUpdate6RN/NewandNoteworthy/NewandNoteworthy.html, which notified me of the com.apple.eawt.Application.setDefaultMenuBar(JMenuBar) method. I already use the Application class, so I added the method in with the menu I wanted, and voila! The method didn't exist, according to eclipse...

    I have the latest version of Java, according to Software Update. It sounds like com.apple.eawt.Application is not included in the java libraries. I suspect com.apple.eawt.Application is included in Macs when you get them.

    Does that mean I need to update some library or something?

    My worst fear is that this might only come with Snow Leopard:

    "Java for Mac OS X 10.6 Update 1 and 10.5 Update 6 Release Notes"

    But it also says 10.5, so I'm completely confused as to whether this is for 10.5 or 10.6.
     
  14. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #14
    Here's the code for what I tried. As written, it tracks the resizing of the frame. Change one line and it doesn't (see below). Tested on 10.5.8, Java 5 and Java 6. Also tested on Java 5, OS 10.4.11 (where it always tracks). Not yet tested on 10.6 because I don't want to reboot right now.


    If you stop trying after your first attempt fails, you'll never get anywhere. You need to be familiar enough with the API that you can think of something else to try. If you don't have the familiarity, and you can't imagine alternatives, then you should consider doing a simpler project.

    Also, when you try something that doesn't work: post your code. You said you can't create off-screen windows, but you didn't post any code. Suppose I'm right, and an off-screen window is the recommendation for a default menubar. Then how would that recommendation ever have been made if off-screen windows are impossible? Next, suppose off-screen windows are possible, but you can't make them work. How would we be able to tell where your code is wrong, if you don't post your code? Or are you just looking for someone else to write all your code for you?


    Code:
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    
    public class SizeWatcher
      extends ComponentAdapter
    {
      public static void
      main( String[] args )
      {
        String text = "Java: " + System.getProperty( "java.version" )
            + " " + System.getProperty( "os.arch" );
    
        JFrame frame = new JFrame( text );
    
        JComponent item = new JLabel( text, JLabel.CENTER );
        item.setBackground( Color.ORANGE );
        item.setOpaque( true );
    
    
        JPanel content = new JPanel();
        content.setLayout( new BorderLayout( 10, 10 ) );
    
        content.add( item, BorderLayout.CENTER );
        content.add( new JLabel( "E" ), BorderLayout.EAST );
        content.add( new JLabel( "W" ), BorderLayout.WEST );
    
        SizeWatcher watcher = new SizeWatcher();
        content.add( watcher.indicatorComponent(), BorderLayout.SOUTH );
    
        content.addComponentListener( watcher );  // ATTACH
    
    
        frame.getContentPane().add( content, BorderLayout.CENTER );
        frame.setSize( 300, 200 );
        frame.setVisible( true );
      }
    
    
      private int lastH, lastW;
      private JLabel label;
    
      public
      SizeWatcher()
      {  label = new JLabel( "w: " + "0000" + " h: " + "0000", JLabel.CENTER );  }
    
      public JComponent
      indicatorComponent()
      {  return label;  }
    
      public void 
      componentResized( ComponentEvent e )
      {
        Component target = e.getComponent();
        if ( target == null )
          return;
    
        int changes = 0;
        Dimension size = target.getSize();
    
        if ( size.width != lastW )
        {
          lastW = size.width;
          ++changes;
        }
    
        if ( size.height != lastH )
        {
          lastH = size.height;
          ++changes;
        }
    
        if ( changes == 0 )
          return;
    
        String text = "w: " + lastW + " h: " + lastH;
        label.setText( text );
      }
    
    }
    
    To make it not track, change this line:
    Code:
        content.addComponentListener( watcher );  // ATTACH
    
    to this:
    Code:
        frame.addComponentListener( watcher );  // ATTACH
    
     

Share This Page