Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

toddburch

macrumors 6502a
Original poster
Dec 4, 2006
748
0
Katy, Texas
Point of reference - I'm new to Java and new to Macs.

I'm coding up a Java Swing application... practicing, practicing, practicing.

I can add a JMenuBar to my JFrame, but....

Question 1: how do I add the JMenu items to the Mac OS menu bar (the topmost, forever present, menubar)?

Then, some other questions:

Question 2: Why doesn't a new instance of this app launch when I click File>New? Obvioulsy, "new RPM();" is not doing what I want it to.

Question 3: Why don't I get a visible separator bar in the File pulldown between OPEN and QUIT?

Here's the code I have so far. File name is RPM.java.

Thanks for any insight. Todd (OS X 10.4.8)

Code:
public class RPM extends javax.swing.JFrame implements 
	java.awt.event.ActionListener, 
	java.awt.event.ComponentListener, 
	java.awt.event.FocusListener {
	javax.swing.JFrame frame ; 
	static final String HNS = "Hide & Seek" ; 
	
	public static void main(String[] args) { 
		
		RPM rpm = new RPM() ; 
		
		// Create a JFrame 
		
		javax.swing.JFrame f = new javax.swing.JFrame("Resize this frame!") ; 
		f.setSize(300,300) ; 
		f.setLocation(100,100) ; 
		rpm.frame = f ; 
		
		// Get the JFrame's container. 
		
		java.awt.Container content = f.getContentPane() ; 
		
		// Add a Single Menu Dropdown.  Do the JMenuItems first.   
		//  File
		//  - New
		//  - Open
		//  - Quit 
		javax.swing.JMenuItem mi_New  = new javax.swing.JMenuItem("New") ; 
		javax.swing.JMenuItem mi_Open = new javax.swing.JMenuItem("Open") ; 
		javax.swing.JMenuItem mi_Quit = new javax.swing.JMenuItem("Quit") ; 
		
		
		// Define all the jmenuitem special behaviors 

		mi_New.setAccelerator(
			javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, java.awt.Event.META_MASK)) ; 
		mi_New.addActionListener(new java.awt.event.ActionListener() { 
			public void actionPerformed(java.awt.event.ActionEvent e) { new RPM() ; } } ) ; 
		
		mi_Open.setAccelerator(
			javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.Event.META_MASK)) ; 
		mi_Open.addActionListener(new java.awt.event.ActionListener() { 
			public void actionPerformed(java.awt.event.ActionEvent e) { System.out.println("Open...") ; } } ) ; 
		
		mi_Quit.setAccelerator(
			javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Q, java.awt.Event.META_MASK)) ; 
		mi_Quit.addActionListener(new java.awt.event.ActionListener() { 
			public void actionPerformed(java.awt.event.ActionEvent e) { System.exit(0) ; } } ) ; 
			
		// Add the File pulldown 
		
		javax.swing.JMenu jMenu = new javax.swing.JMenu("File") ; 
		jMenu.add(mi_New) ; 
		jMenu.add(mi_Open) ; 
		jMenu.addSeparator() ; 
		jMenu.add(mi_Quit) ;
		
		// Get a JMenuBar, add out JMenu to it, and then ad it to the JFrame 
		
		javax.swing.JMenuBar jMenuBar = new javax.swing.JMenuBar() ; 
		jMenuBar.add(jMenu) ; 
		f.setJMenuBar(jMenuBar) ; 
				
		// Set the Layout Manager 
		content.setLayout(new java.awt.FlowLayout()) ; 

		// Add some widgets 
		
		content.add(new javax.swing.JLabel("Dumb Label")) ; 
		
		javax.swing.JButton myButton1 = new javax.swing.JButton("Mango") ; 
		javax.swing.JButton myButton2 = new javax.swing.JButton(HNS) ; 
		
		myButton1.addActionListener(rpm) ; 
		myButton2.addActionListener(rpm) ; 
		content.add(myButton1) ; 
		content.add(myButton2) ;  
		
		//* Add a JTextField 
		javax.swing.JTextField textField = new javax.swing.JTextField(20) ;  // 20 columns wide
		content.add(textField) ; 
		textField.addFocusListener(rpm) ; 
		
		//f.pack() ;   // Collapse the window to the bare minimum size 
		
		f.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE) ; // Close app when RED X is clicked.
		f.addComponentListener(rpm) ; 
		
		f.setVisible(true) ;  // make window appear 
		
	}
	
	public void actionPerformed(java.awt.event.ActionEvent ae) { 
		System.out.println("Button pressed...") ; 
		System.out.println("ae.getActionCommand()=" + ae.getActionCommand() ) ; 
		System.out.println("Modifiers are=" + ae.getModifiers() ) ; 
		if (ae.getActionCommand() == HNS) { 
			this.frame.setVisible(false) ;  // Disappear for 1 second 
			try { 
				Thread.sleep(1000) ;   // sleep for 1 second 
			}
			catch (Exception e) {} 
			this.frame.setVisible(true) ;   // Make the screen visible again.
		} 
	} 

	public void componentHidden(java.awt.event.ComponentEvent ce) {  // Fired when window is not visible
		System.out.println("Component Event Fired = Hidden") ;       // See "Hide & Seek" (HNS) button. 
	} 
	public void componentShown(java.awt.event.ComponentEvent ce) { 
		System.out.println("Component Event Fired = Shown") ; 
	} 
	public void componentMoved(java.awt.event.ComponentEvent ce) { 
		System.out.println("Component Event Fired = Moved") ; 
	} 	
	public void componentResized(java.awt.event.ComponentEvent ce) { 
		System.out.println("Component Event Fired = Resized") ; 
		this.frame.setTitle("Width=" + this.frame.getWidth() + ", Height=" + this.frame.getHeight() ) ; 
	} 
	public void focusGained(java.awt.event.FocusEvent fe) {    // Fires when the JTextField is clicked 
		System.out.println("Keyboard Focus: Gained") ; 
	} 
	public void focusLost(java.awt.event.FocusEvent fe) { 
		System.out.println("Keyboard Focus: Lost") ; 
	} 
}
 

portent

macrumors 6502a
Feb 17, 2004
623
2
Answer 1:: Call
Code:
System.setProperty("apple.laf.useScreenMenuBar", "true");
in your main() method.

Answer 2: All of your code is in the main() method, which gets called exactly once (when you first run the program.) So you get exactly one window.

The ActionListener for the "New" menu item is just creating a new RPM instance. It creates it, in memory, but doesn't do anything with it.

To get what you want, you'd need to move most of your code from the main() into a constructor method for the RPM class. Have your main method call new rpm().

Answer 3 I don't rightly know, off the top of my head, and I'm too lazy to find out.
 

toddburch

macrumors 6502a
Original poster
Dec 4, 2006
748
0
Katy, Texas
Thanks portent - you got me on the right track.

I pulled all but the essentials out of main() into RPM(). Worked great.

Then, I added the System.setProperty - worked perfectly! Now I'll figure out how to tell what platform I'm running on, so when this runs on Windows, it won't issue the call. Research project for me. Something in the back of my mind tells me there will be a method i need in the System class... ;)

Then, I figured out why the File>New wasn't working. Basically, I needed to set it visible. Modfifying the routine to new up an RPM() and then setVisible on it worked perfect... almost. Now I get to go back and take out all the System.exit(0) calls and change them to JFrame kills so when I close any frame, only that frame will go away. Another research project for me.

Thanks again. :)
Todd

Code:
public class RPM extends javax.swing.JFrame implements 
	java.awt.event.ActionListener, 
	java.awt.event.ComponentListener, 
	java.awt.event.FocusListener {

	static final String HNS = "Hide & Seek" ; 

	// Main Method.   Create a JFrame and Display it. 	
	public static void main(String[] args) { 
	
		System.setProperty("apple.laf.useScreenMenuBar", "true");   // Use Mac's menubar. 
		javax.swing.JFrame rpm = new RPM() ; 
		rpm.setVisible(true) ; 

	}

	
	public RPM() { 
		super("RPM V1.0") ; 
		
		this.setTitle("Resize this frame!") ; 
		this.setSize(300,300) ; 
		this.setLocation(100,100) ; 
		

		java.awt.Container content = this.getContentPane() ; 
		
		// Add a Single Menu Dropdown.  Do the JMenuItems first.   
		//  File
		//  - New
		//  - Open
		//  - Quit 
		javax.swing.JMenuItem mi_New  = new javax.swing.JMenuItem("New") ; 
		javax.swing.JMenuItem mi_Open = new javax.swing.JMenuItem("Open") ; 
		javax.swing.JMenuItem mi_Quit = new javax.swing.JMenuItem("Quit") ; 
		
		
		// Define all the jmenuitem special behaviors 

		mi_New.setAccelerator(
			javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, java.awt.Event.META_MASK)) ; 
		mi_New.addActionListener(new java.awt.event.ActionListener() { 
			public void actionPerformed(java.awt.event.ActionEvent e) { 
				javax.swing.JFrame newFrame = new RPM() ; 
				newFrame.setVisible(true) ; 
			} } ) ; 
		
		mi_Open.setAccelerator(
			javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.Event.META_MASK)) ; 
		mi_Open.addActionListener(new java.awt.event.ActionListener() { 
			public void actionPerformed(java.awt.event.ActionEvent e) { System.out.println("Open...") ; } } ) ; 
		
		mi_Quit.setAccelerator(
			javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Q, java.awt.Event.META_MASK)) ; 
		mi_Quit.addActionListener(new java.awt.event.ActionListener() { 
			public void actionPerformed(java.awt.event.ActionEvent e) { System.exit(0) ; } } ) ; 
			
		// Add the File pulldown 
		
		javax.swing.JMenu jMenu = new javax.swing.JMenu("File") ; 
		jMenu.add(mi_New) ; 
		jMenu.add(mi_Open) ; 
		jMenu.addSeparator() ; 
		jMenu.add(mi_Quit) ;
		
		// Get a JMenuBar, add out JMenu to it, and then ad it to the JFrame 
		
		javax.swing.JMenuBar jMenuBar = new javax.swing.JMenuBar() ; 
		jMenuBar.add(jMenu) ; 
		this.setJMenuBar(jMenuBar) ; 
				
		// Set the Layout Manager 
		content.setLayout(new java.awt.FlowLayout()) ; 

		// Add some widgets 
		
		content.add(new javax.swing.JLabel("Dumb Label")) ; 
		
		javax.swing.JButton myButton1 = new javax.swing.JButton("Mango") ; 
		javax.swing.JButton myButton2 = new javax.swing.JButton(HNS) ; 
		
		myButton1.addActionListener(this) ; 
		myButton2.addActionListener(this) ; 
		content.add(myButton1) ; 
		content.add(myButton2) ;  
		
		//* Add a JTextField 
		javax.swing.JTextField textField = new javax.swing.JTextField(20) ;  // 20 columns wide
		content.add(textField) ; 
		textField.addFocusListener(this) ; 
		
		//this.pack() ;   // Collapse the window to the bare minimum size 
		
		this.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE) ; // Close app when RED X is clicked.
		this.addComponentListener(this) ; 
		
		
	}

	public void actionPerformed(java.awt.event.ActionEvent ae) { 
		System.out.println("Button pressed...") ; 
		System.out.println("ae.getActionCommand()=" + ae.getActionCommand() ) ; 
		System.out.println("Modifiers are=" + ae.getModifiers() ) ; 
		if (ae.getActionCommand() == HNS) { 
			this.setVisible(false) ;  // Disappear for 1 second 
			try { 
				Thread.sleep(1000) ;   // sleep for 1 second 
			}
			catch (Exception e) {} 
			this.setVisible(true) ;   // Make the screen visible again.
		} 
	} 

	public void componentHidden(java.awt.event.ComponentEvent ce) {  // Fired when window is not visible
		System.out.println("Component Event Fired = Hidden") ;       // See "Hide & Seek" (HNS) button. 
	} 
	public void componentShown(java.awt.event.ComponentEvent ce) { 
		System.out.println("Component Event Fired = Shown") ; 
	} 
	public void componentMoved(java.awt.event.ComponentEvent ce) { 
		System.out.println("Component Event Fired = Moved") ; 
	} 	
	public void componentResized(java.awt.event.ComponentEvent ce) { 
		System.out.println("Component Event Fired = Resized") ; 
		this.setTitle("Width=" + this.getWidth() + ", Height=" + this.getHeight() ) ; 
	} 
	public void focusGained(java.awt.event.FocusEvent fe) {    // Fires when the JTextField is clicked 
		System.out.println("Keyboard Focus: Gained") ; 
	} 
	public void focusLost(java.awt.event.FocusEvent fe) { 
		System.out.println("Keyboard Focus: Lost") ; 
	} 
}
 

toddburch

macrumors 6502a
Original poster
Dec 4, 2006
748
0
Katy, Texas
Well that didn't take too long...

Code:
String sys = System.getProperty("os.name").substring(0,3) ; 
System.out.println("->" + sys + "<-") ; 
		
if (sys.equalsIgnoreCase("Mac")) {  
	System.setProperty("apple.laf.useScreenMenuBar", "true");   
}

However, in the end, Windows appeared to ignore the call anyways. But, it's cleaner.

Thanks again.
 

therevolution

macrumors 6502
May 12, 2003
468
0
There's no harm in calling

System.setProperty("apple.laf.useScreenMenuBar", "true");

on Windows. As you found out, the Windows JVM will simply ignore that property. I don't really agree that it's "cleaner" to add the check first - I bet the check uses up more cycles than simply setting the property, not to mention it clutters up your code.

But this is a pretty trivial thing for me to nitpick. Just felt like pointing it out anyway. :p
 

toddburch

macrumors 6502a
Original poster
Dec 4, 2006
748
0
Katy, Texas
I researched this a litle more; found it documented in the XCode Help>Documentation. It appears this system property can be used as a command line option as well:

java -Dapple.laf.useScreenMenuBar="true" yourApplication

The purpose the added logic is serving - allowing me to learn more about the Java environment, the Mac environment and Java programming - is a greater need right now than it's performance implication. ;)

Thanks for the feedback. It's always welcome - no matter how nitpicky. The beauty of any (nitpicky or otherwise) comment about code or coding style is that I can take it or leave it. No harm, no foul.

Todd
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.