How do I bring my JFrame into focus

Hi all,

I'm using a JFrame to display help content in a JEditorPane. The help frame is started up when the user clicks on the "Help" menu. Unfortunately, the help frame does not have focus nor is it at the front.

Good examples of the effect I'm looking for are in Firefox and Internet Explorer. In Firefox, go to Help then Help Contents. In IE go to Help then Contents and Index.

A small example of my current code is below.

package helpMenu;

import javax.swing.JEditorPane;

import javax.swing.JFrame;

import javax.swing.JMenu;

import javax.swing.JMenuBar;

import javax.swing.event.MenuEvent;

import javax.swing.event.MenuListener;

publicclass MyWindowextends JFrame

{

public MyWindow()

{

// JFrame settings.

setTitle("Help Menu Demo");

setSize(800,600);

setLocationRelativeTo(null);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// Menu bar / menus.

JMenuBar menuBar=new JMenuBar();

JMenu help=new JMenu("Help");

help.addMenuListener(new MListener("Help"));

menuBar.add(help);

setJMenuBar(menuBar);

setVisible(true);

}

// Inner class to handle JMenu actions.

privateclass MListenerimplements MenuListener

{

String name;

public MListener(String nm)

{

name= nm;

}

// Invoked when the menu is selected.

publicvoid menuSelected(MenuEvent me)

{

if (name.equals("Help"))

{

JFrame helpFrame=new JFrame("Help");

helpFrame.setSize(200,500);

JEditorPane helpContent=new JEditorPane();

helpFrame.add(helpContent);

helpFrame.setVisible(true);

}

}

// Invoked when the menu is cancelled.

publicvoid menuCanceled(MenuEvent me)

{

}

// Invoked when the menu is deselected.

publicvoid menuDeselected(MenuEvent me)

{

}

}

publicstaticvoid main(String[] args)

{

new MyWindow();

}

}

thanks,

john

[3977 byte] By [johnmcparlalda] at [2007-10-3 3:46:24]
# 1
use JDialog for the help frame and set the MyWindow instance as the parent
lfschucka at 2007-7-14 21:43:06 > top of Java-index,Desktop,Core GUI APIs...
# 2

Thanks, that's partly solved my problem. The help dialog is at the front (and I set it's location too) but it is not the selected component.

I could do this by making it modal, but I do not want to - In the real app I want the user to perform actions on the main frame and look at the help.

Any ideas?

package helpMenu;

import javax.swing.JDialog;

import javax.swing.JEditorPane;

import javax.swing.JFrame;

import javax.swing.JMenu;

import javax.swing.JMenuBar;

import javax.swing.event.MenuEvent;

import javax.swing.event.MenuListener;

public class MyWindow extends JFrame

{

private JDialog helpDialog;

private JEditorPane helpContent;

public MyWindow()

{

// JFrame settings.

setTitle("Help Menu Demo");

setSize(800,600);

setLocationRelativeTo(null);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// Menu bar / menus.

JMenuBar menuBar= new JMenuBar();

JMenu help= new JMenu("Help");

help.addMenuListener(new MListener("Help"));

menuBar.add(help);

setJMenuBar(menuBar);

// The help dialog.

setupHelpDialog();

setVisible(true);

}

private void setupHelpDialog()

{

helpDialog= new JDialog(this, "MyWindow Help", false);

helpDialog.setSize(250,700);

helpDialog.setLocation(this.getSize().width,this.getSize().height-350);

helpContent= new JEditorPane();

helpDialog.add(helpContent);

helpDialog.setVisible(false);

}

// Inner class to handle JMenu actions.

private class MListener implements MenuListener

{

String name;

public MListener(String nm)

{

name= nm;

}

// Invoked when the menu is selected.

public void menuSelected(MenuEvent me)

{

if (name.equals("Help"))

{

helpDialog.toFront();

helpDialog.setVisible(true);

}

}

// Invoked when the menu is cancelled.

public void menuCanceled(MenuEvent me)

{

helpDialog.setVisible(false);

}

// Invoked when the menu is deselected.

public void menuDeselected(MenuEvent me)

{

}

}

public static void main(String[] args)

{

new MyWindow();

}

}

johnmcparlalda at 2007-7-14 21:43:06 > top of Java-index,Desktop,Core GUI APIs...
# 3
Er... how about the toFront() method? :o)JDialog is, I would suggest, not what you want. If it's modal it blocks the rest of the UI and if it isn't then it doesn't have a taskbar button so it's easy to lose.
itchyscratchya at 2007-7-14 21:43:06 > top of Java-index,Desktop,Core GUI APIs...
# 4

> Er... how about the toFront() method? :o)

look in the code - it's there in the updated

public void menuSelected(MenuEvent me)

method.

>

> JDialog is, I would suggest, not what you want. If

> it's modal it blocks the rest of the UI and if it

> isn't then it doesn't have a taskbar button so it's

> easy to lose.

well what is better - I'm asking because I've tried a few things and it hasn't worked.

any ideas anyone?

johnmcparlalda at 2007-7-14 21:43:06 > top of Java-index,Desktop,Core GUI APIs...
# 5
it's there in the updated public void menuSelected(MenuEvent me) method.Ah, sorry, didn't read the second one.Swap the lines so it comes immediately after the call to setVisible(true).
itchyscratchya at 2007-7-14 21:43:06 > top of Java-index,Desktop,Core GUI APIs...
# 6
> Swap the lines so it comes immediately after the call to setVisible(true).that didn't work either - surely a help dialog's been done a million times. Unfortunately google "java help menu" and you get millions of "java help" or "help me please" java forum posts.
johnmcparlalda at 2007-7-14 21:43:06 > top of Java-index,Desktop,Core GUI APIs...
# 7

Hm, works fine for me. In fact it works without even using toFront(). And toBack() works too.

What platform are you on? (VM version, OS)

Try this - working fine here under XP with 1.4.2

import java.awt.BorderLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JLabel;

import javax.swing.SwingUtilities;

public final class FrameToFront

{

private static boolean first = true;

public static final void main(String[] args)

{

SwingUtilities.invokeLater(new Runnable() {

public void run()

{

launch();

}

});

}

private static final void launch()

{

JFrame f = new JFrame();

if (first)

{

f.getContentPane().add(new JLabel("Main frame - close this one to exit", JLabel.CENTER), BorderLayout.NORTH);

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

first = false;

}

JButton b = new JButton("New Frame");

b.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e)

{

launch();

}

});

f.getContentPane().add(b);

f.pack();

f.setLocationRelativeTo(null);

f.setVisible(true);

f.toFront();

}

}

itchyscratchya at 2007-7-14 21:43:06 > top of Java-index,Desktop,Core GUI APIs...
# 8
I'm using XP Pro and jdk / jre 1.5.0_07Your example worked fine for me - I wonder why there's a difference in my example under 1.4.2 and 1.5.0Are you sure that when you run mine not only is the help dialog at the front but it is also the selected window?John
johnmcparlalda at 2007-7-14 21:43:06 > top of Java-index,Desktop,Core GUI APIs...
# 9

No, yours doesn't work. I've just tested it and it's a threading issue.

You have two choices - A and B below show the modifications.

A uses ActionListener on a JMenuItem instead of firing from the JMenu itself. I'd suggest using this, since that's where you'd normally fire events from, not from the actual menu. (In fact I'd suggest using Actions instead of ActionListeners, but that's a separate topic). ActionEvents are generated on the event dispatch thread (EDT) which you must be using to construct and modify UI components (ie your help frame).

It would appear that there is a quirk with the MenuEvent generation and the UI engine isn't in a state where it allows new frames to be generated properly. I've no idea why this is and it's not worth my while to look into it :o) ...but it may be a Swing bug. Worth checking on the bug database.

So, solution B uses MenuListener but returns from the event handling before hooking back onto the EDT to do its work. If you really need MenuListener then you might want to use this as a model, but I'd suggest you probably don't :o)

I've never needed to use MenuListener before so I've never come across this bug until now.

A - using ActionListener

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import javax.swing.JEditorPane;

import javax.swing.JFrame;

import javax.swing.JMenu;

import javax.swing.JMenuBar;

import javax.swing.JMenuItem;

import javax.swing.SwingUtilities;

import javax.swing.event.MenuEvent;

public class MyWindow extends JFrame

{

public MyWindow()

{

// JFrame settings.

setTitle("Help Menu Demo");

setSize(800,600);

setLocationRelativeTo(null);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// Menu bar / menus.

JMenuBar menuBar= new JMenuBar();

JMenu help= new JMenu("Help");

JMenuItem helpItem = new JMenuItem("Index...");

help.add(helpItem);

helpItem.addActionListener(new MListener("Help"));

menuBar.add(help);

setJMenuBar(menuBar);

setVisible(true);

}

// Inner class to handle JMenu actions.

private class MListener implements ActionListener

{

String name;

public MListener(String nm)

{

name= nm;

}

// Invoked when the menu is selected.

public void actionPerformed(ActionEvent me)

{

if (name.equals("Help"))

{

JFrame helpFrame= new JFrame();

helpFrame.setSize(200,500);

JEditorPane helpContent= new JEditorPane();

helpFrame.getContentPane().add(helpContent);

helpFrame.pack();

helpFrame.setVisible(true);

}

}

// Invoked when the menu is cancelled.

public void menuCanceled(MenuEvent me)

{

}

// Invoked when the menu is deselected.

public void menuDeselected(MenuEvent me)

{

}

}

public static void main(String[] args)

{

SwingUtilities.invokeLater(new Runnable() {

public void run() { new MyWindow(); }

});

}

}

B - using MenuListener

import javax.swing.JEditorPane;

import javax.swing.JFrame;

import javax.swing.JMenu;

import javax.swing.JMenuBar;

import javax.swing.SwingUtilities;

import javax.swing.event.MenuEvent;

import javax.swing.event.MenuListener;

public class MyWindow extends JFrame

{

public MyWindow()

{

// JFrame settings.

setTitle("Help Menu Demo");

setSize(800,600);

setLocationRelativeTo(null);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// Menu bar / menus.

JMenuBar menuBar= new JMenuBar();

JMenu help= new JMenu("Help");

help.addMenuListener(new MListener("Help"));

menuBar.add(help);

setJMenuBar(menuBar);

setVisible(true);

}

// Inner class to handle JMenu actions.

private class MListener implements MenuListener, Runnable

{

String name;

public MListener(String nm)

{

name= nm;

}

// Invoked when the menu is selected.

public void menuSelected(MenuEvent me)

{

SwingUtilities.invokeLater(this);

}

public void run()

{

if (name.equals("Help"))

{

JFrame helpFrame= new JFrame("Help");

helpFrame.setSize(200,500);

JEditorPane helpContent= new JEditorPane();

helpFrame.getContentPane().add(helpContent);

helpFrame.setVisible(true);

}

}

// Invoked when the menu is cancelled.

public void menuCanceled(MenuEvent me)

{

}

// Invoked when the menu is deselected.

public void menuDeselected(MenuEvent me)

{

}

}

public static void main(String[] args)

{

new MyWindow();

}

}

itchyscratchya at 2007-7-14 21:43:06 > top of Java-index,Desktop,Core GUI APIs...
# 10

Sorry for the late reply - I had another important task to take care of (+ sleep etc).

Thanks for your help - your B example was the kind of thing I was looking for. I modified it a little to ensure that the "Help" frame can only be opened once and if someone tries to open it again, it is merely brought to the front again. This code can be viewed at the bottom.

Thanks again.

package helpMenu;

import javax.swing.JEditorPane;

import javax.swing.JFrame;

import javax.swing.JMenu;

import javax.swing.JMenuBar;

import javax.swing.SwingUtilities;

import javax.swing.event.MenuEvent;

import javax.swing.event.MenuListener;

public class MyWindow extends JFrame

{

protected static boolean helpOpen= false;

public MyWindow()

{

// JFrame settings.

setTitle("Help Menu Demo");

setSize(800,600);

setLocationRelativeTo(null);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// Menu bar / menus.

JMenuBar menuBar= new JMenuBar();

JMenu help= new JMenu("Help");

//setupHelpFrame();

help.addMenuListener(new MListener("Help"));

menuBar.add(help);

setJMenuBar(menuBar);

setVisible(true);

}

// Inner class to handle JMenu actions.

private class MListener implements MenuListener, Runnable

{

private String name;

private JFrame helpFrame;

public MListener(String nm)

{

name= nm;

}

// Invoked when the menu is selected.

public void menuSelected(MenuEvent me)

{

SwingUtilities.invokeLater(this);

}

public void run()

{

if (name.equals("Help") & !helpOpen)

{

helpOpen= true;

helpFrame= new JFrame("Help");

helpFrame.setSize(200,500);

helpFrame.setLocationRelativeTo(null);

JEditorPane helpContent= new JEditorPane();

helpFrame.getContentPane().add(helpContent);

helpFrame.setVisible(true);

}

else if (name.equals("Help") & helpOpen)

{

helpFrame.toFront();

}

}

// Invoked when the menu is cancelled.

public void menuCanceled(MenuEvent me)

{

helpOpen= false;

helpFrame.dispose();

}

// Invoked when the menu is deselected.

public void menuDeselected(MenuEvent me)

{

}

}

public static void main(String[] args)

{

new MyWindow();

}

}

johnmcparlalda at 2007-7-14 21:43:06 > top of Java-index,Desktop,Core GUI APIs...
# 11

Good stuff. I would still *strongly* suggest using solution A, though:

- it uses a conventional UI pattern instead of one I've never seen used

- it allows you to use Actions which means the code is much less fragile (you have five (!!) string constants with "Help" in, which is very bad practice - both repeating a magic string and cooking the English language in as well)

- it doesn't require a workaround for a bug

- you don't get an odd-looking empty menu appear when you click the help menu title

- written properly it uses much less code

Need any more reasons? :o)

itchyscratchya at 2007-7-14 21:43:06 > top of Java-index,Desktop,Core GUI APIs...
# 12

Only problem is that it needs to be a JMENU.

I tried adding an action listener to the help menu but that doesn't seem to work.

package ui;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import javax.swing.JEditorPane;

import javax.swing.JFrame;

import javax.swing.JMenu;

import javax.swing.JMenuBar;

public class MyWindow extends JFrame

{

protected static boolean helpOpen= false;

public MyWindow()

{

// JFrame settings.

setTitle("Help Menu Demo");

setSize(800,600);

setLocationRelativeTo(null);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// Menu bar / menus.

JMenuBar menuBar= new JMenuBar();

JMenu help= new JMenu("Help");

//setupHelpFrame();

help.addActionListener(new MListener("Help"));

menuBar.add(help);

setJMenuBar(menuBar);

setVisible(true);

}

// Inner class to handle JMenu actions.

private class MListener implements ActionListener, Runnable

{

private String name;

private JFrame helpFrame;

public MListener(String nm)

{

name= nm;

}

public void actionPerformed(ActionEvent ae)

{

System.out.println("in actionPerformed");

this.run();

}

public void run()

{

if (name.equals("Help") & !helpOpen)

{

System.out.println("help was not already open");

helpOpen= true;

helpFrame= new JFrame("Help");

helpFrame.setSize(200,500);

helpFrame.setLocationRelativeTo(null);

JEditorPane helpContent= new JEditorPane();

helpFrame.getContentPane().add(helpContent);

System.out.println("going to show helpFrame");

helpFrame.setVisible(true);

}

else if (name.equals("Help") & helpOpen)

{

System.out.println("help is already open");

helpFrame.toFront();

}

}

}

public static void main(String[] args)

{

new MyWindow();

}

}

johnmcparlalda at 2007-7-14 21:43:06 > top of Java-index,Desktop,Core GUI APIs...
# 13

Only problem is that it needs to be a JMENU.

Why? As in my first point, it's an approach that's never used elsewhere. Not that I've seen anyway (well not on Windows certainly) - and as in the fourth point, it leaves you a dangling menu.

If I click on a menu title, I expect a menu to drop down, I don't expect windows to start opening.

itchyscratchya at 2007-7-14 21:43:06 > top of Java-index,Desktop,Core GUI APIs...
# 14

Well I don't have anywhere else on the interface to put it - the real one, not the toy one that is.

I might be better having a jmenuitem that says index or something similar - that way i'm still fullfilling customer requirements ("help menu required") and doing something that is actually possible.

thanks again

johnmcparlalda at 2007-7-14 21:43:06 > top of Java-index,Desktop,Core GUI APIs...
# 15
Well that's the normal way of doing it.You quite often find other things under the Help menu as well - the "About" option is the common one. You could throw that in if you're uncomfortable with the idea of a menu with only one item in it :o)
itchyscratchya at 2007-7-21 10:17:47 > top of Java-index,Desktop,Core GUI APIs...