I have a JFrame with a JMenuBar that I'm developing and testing on a Mac system. On this JFrame, I have programmed one of the JMenus to be disabled. However, when I change focus from my Java application to some other program on my computer and then come back to this JFrame, strange things are happening. I have observed that all of the menus become disabled. I have also observed that all of the menus become enabled. Can anyone tell me what's going on here?
Here's a piece of code that will reproduce the error (at least it does on my machine):
public class MenuProblemExample {
public static void main(String[] args) {
System.setProperty("apple.laf.useScreenMenuBar", "true");
JFrame frame = new JFrame();
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
fileMenu.add(new JMenuItem("open"));
menuBar.add(fileMenu);
JMenu editMenu = new JMenu("Edit");
editMenu.add(new JMenuItem("select all"));
menuBar.add(fileMenu);
menuBar.add(editMenu);
frame.setJMenuBar(menuBar);
fileMenu.setEnabled(false);
frame.setVisible(true);
}
}
When I run this, the enabled property isn't stable under the action of switching focus to another window and then back again.
Swing GUI objects should be constructed and manipulated only on the event dispatch thread.
By design, Mac applications using the screen menubar disable menus in the background. It is up to your application to enable menus appropriately when your application comes to the foreground, using e.g. a WindowListener.
Addendum: For testing, this revised example adds a toggle button that tracks the state of the File > Open menu item.
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JToggleButton;
/**
* #see http://stackoverflow.com/a/13756527/230513
*/
public class MenuProblemExample {
public static void main(String[] args) {
System.setProperty("apple.laf.useScreenMenuBar", "true");
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
final JMenuItem openItem = new JMenuItem("open");
openItem.setEnabled(false);
fileMenu.add(openItem);
menuBar.add(fileMenu);
JMenu editMenu = new JMenu("Edit");
editMenu.add(new JMenuItem("select all"));
menuBar.add(fileMenu);
menuBar.add(editMenu);
frame.setJMenuBar(menuBar);
frame.add(new JToggleButton(new AbstractAction("Toggle") {
#Override
public void actionPerformed(ActionEvent e) {
JToggleButton b = (JToggleButton) e.getSource();
openItem.setEnabled(b.isSelected());
}
}));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Related
I know how to code Java but I'm having a lot of trouble with this. I've made a menubar but I want to put a split pane underneath it. The menubar is fine but the split pane is giving me a lot of errors and I don't know how to fix it.
Any help would be much appreciated.
package getcodinggui;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.JFrame;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
public class GetCodingGUI {
JTextArea output;
JScrollPane scrollPane;
public JMenuBar createMenuBar() {
JMenuBar menuBar;
JMenu menu;
menuBar = new JMenuBar();
menu = new JMenu("Home");
menu.setMnemonic(KeyEvent.VK_A);
menu.getAccessibleContext().setAccessibleDescription(
"File Menu Items");
menuBar.add(menu);
menu = new JMenu("About");
menu.setMnemonic(KeyEvent.VK_N);
menu.getAccessibleContext().setAccessibleDescription(
"Edit Menu Items");
menuBar.add(menu);
menu = new JMenu("Contact Us");
menu.setMnemonic(KeyEvent.VK_N);
menu.getAccessibleContext().setAccessibleDescription(
"Edit Menu Items");
menuBar.add(menu);
menu = new JMenu("FAQ");
menu.setMnemonic(KeyEvent.VK_N);
menu.getAccessibleContext().setAccessibleDescription(
"Edit Menu Items");
menuBar.add(menu);
menu = new JMenu("Log In");
menu.setMnemonic(KeyEvent.VK_N);
menu.getAccessibleContext().setAccessibleDescription(
"Edit Menu Items");
menuBar.add(menu);
return menuBar;
}
public Container createContentPane() {
//Create the content-pane-to-be.
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.setOpaque(true);
//Create a scrolled text area.
output = new JTextArea(5, 30);
output.setEditable(false);
scrollPane = new JScrollPane(output);
//Add the text area to the content pane.
contentPane.add(scrollPane, BorderLayout.CENTER);
return contentPane;
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
public static class MyJFrameWin extends JFrame{
JSplitPane jSplitPane, jSplitPane2;
JPanel jPanel1, jPanel2a, jPanel2b;
jPanel1 = new JPanel();
jPanel2a = new JPanel();
jPanel2b = new JPanel();
jSplitPane2 = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
jPanel2a, jPanel2b);
jSplitPane2.setOneTouchExpandable(true);
jSplitPane2.setDividerLocation(100);
jSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
jPanel1, jSplitPane2);
jSplitPane.setOneTouchExpandable(true);
jSplitPane.setDividerLocation(150);
getContentPane().add(jSplitPane);
}
}
//Create and set up the content pane.
GetCodingGUI demo = new GetCodingGUI();
frame.setJMenuBar(demo.createMenuBar());
frame.setContentPane(demo.createContentPane());
//Display the window.
frame.setSize(1280, 720);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(runJSplitPaneLater);
}
javax.swing.SwingUtilities.invokeLater(new Runnable, runJSplitPaneLater()
{
static Runnable runJSplitPaneLater = new Runnable(){
#Override
public void run() {
MyJFrameWin myJFrameWin = new MyJFrameWin();
myJFrameWin.setVisible(true);
createAndShowGUI();
}
});
}
}
I had to clean up 20 compile errors.
Here's the GUI I created.
Here are the changes I made.
I rearranged all of your code. Code is much easier to understand when it reads from top to bottom.
Since the SwingUtilities invokeLater method requires a Runnable, I made your GUI view class implement Runnable.
I put your content pane in one of the JSplitPanes. I just guessed which pane.
I put the outer JSplitPane into the JFrame.
I fixed your menu alt keys.
I returned a JPanel from your createContentPane method.
I formatted your code.
I reduced the size of your JFrame so it would fit on my screen.
Here's the code:
package com.ggl.testing;
import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class GetCodingGUI implements Runnable {
private JTextArea output;
private JScrollPane scrollPane;
public static void main(String[] args) {
SwingUtilities.invokeLater(new GetCodingGUI());
}
#Override
public void run() {
// Create and set up the window.
JFrame frame = new JFrame("Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JSplitPane jSplitPane, jSplitPane2;
JPanel jPanel1, jPanel2a, jPanel2b;
jPanel1 = new JPanel();
jPanel2a = new JPanel();
jPanel2b = createContentPane();
jSplitPane2 = new JSplitPane(JSplitPane.VERTICAL_SPLIT, jPanel2a,
jPanel2b);
jSplitPane2.setOneTouchExpandable(true);
jSplitPane2.setDividerLocation(100);
jSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, jPanel1,
jSplitPane2);
jSplitPane.setOneTouchExpandable(true);
jSplitPane.setDividerLocation(150);
frame.add(jSplitPane);
frame.setJMenuBar(createMenuBar());
// Display the window.
frame.setSize(800, 600);
frame.setVisible(true);
}
public JMenuBar createMenuBar() {
JMenuBar menuBar;
JMenu menu;
menuBar = new JMenuBar();
menu = new JMenu("Home");
menu.setMnemonic(KeyEvent.VK_H);
menu.getAccessibleContext().setAccessibleDescription("File Menu Items");
menuBar.add(menu);
menu = new JMenu("About");
menu.setMnemonic(KeyEvent.VK_A);
menu.getAccessibleContext().setAccessibleDescription("Edit Menu Items");
menuBar.add(menu);
menu = new JMenu("Contact Us");
menu.setMnemonic(KeyEvent.VK_C);
menu.getAccessibleContext().setAccessibleDescription("Edit Menu Items");
menuBar.add(menu);
menu = new JMenu("FAQ");
menu.setMnemonic(KeyEvent.VK_F);
menu.getAccessibleContext().setAccessibleDescription("Edit Menu Items");
menuBar.add(menu);
menu = new JMenu("Log In");
menu.setMnemonic(KeyEvent.VK_L);
menu.getAccessibleContext().setAccessibleDescription("Edit Menu Items");
menuBar.add(menu);
return menuBar;
}
public JPanel createContentPane() {
// Create the content-pane-to-be.
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.setOpaque(true);
// Create a scrolled text area.
output = new JTextArea(5, 30);
output.setEditable(false);
scrollPane = new JScrollPane(output);
// Add the text area to the content pane.
contentPane.add(scrollPane, BorderLayout.CENTER);
return contentPane;
}
}
Following is my code.
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
public class MenuBarProblem {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(new Dimension(300, 400));
JMenu menu1 = new JMenu("First");
JMenuItem item = new JMenuItem("Add menu");
menu1.add(item);
final JMenuBar mb = new JMenuBar();
mb.add(menu1);
frame.setJMenuBar(mb);
item.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
JMenu menu1 = new JMenu("First");
JMenuItem item = new JMenuItem("Add menu");
menu1.add(item);
mb.add(menu1);
System.out.println(mb.getMenuCount());
}
});
frame.setVisible(true);
}
}
What I want to do is to add menus to the menubar when the menu item1 is clicked. The line System.out.println(mb.getMenuCount()); prints that the menu items are being added. (It prints 2,3,4 when the menu item1 is clicked) but the menus don't show up in the menu bar.
What should I do so that the menu items that are dynamically added get shown on the menubar? I'm using Java 1.6.
After adding the extra menu in mb use:
mb.revalidate();
This causes the component to get replainted, after the newly added menu has been inserted into the component tree.
Try calling repaint after
frame.setVisible(true);
as
frame.repaint();
I have a problem when i want insert a separator with JSeparator for Java Swing application. In point of fact, I have this problem just when i run my program on Mac, i haven't it on windows or linux. The separator is incorrectly placed, the text is strikethrough. Does anyone know why?
My code :
JMenuItem fileItem = new JMenuItem("Close");
KeyStroke ...
fileItem.add(new JSeparator(JSeparator.HORIZONTAL),BorderLayout.LINE_START);
Screenshot :
Basically your code right now shows that you are assuming JMenuItem has a default BorderLayout, which could be true (but I dont think so).
Though the root problem is you are adding the JSeparator to the JMenuItem when in fact you should add it to the JMenu which contains the various JMenuItems via JMenu#addSeparator(). See How to Use Separators for more.
You should be doing something like:
JMenu menu=new JMenu();
JMenuItem item1=new JMenuItem("something 1");
JMenuItem item2=new JMenuItem("something 1");
menu.add(item1);
menu.addSeparator();//lets add that separator
menu.add(item2);
giving you something like:
UPDATE:
Here is an example:
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
public class Test {
public Test() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JMenuBar menuBar=new JMenuBar();
JMenu menu = new JMenu("File");
JMenu menu2 = new JMenu("Else");
JMenuItem item1 = new JMenuItem("something 1");
JMenuItem item2 = new JMenuItem("something 2");
JMenuItem item3 = new JMenuItem("else 1");
JMenuItem item4 = new JMenuItem("else 2");
menu2.add(item3);
menu2.addSeparator();//lets add that separator
menu2.add(item4);
menu.add(menu2);
menu.add(item1);
menu.addSeparator();//lets add that separator
menu.add(item2);
menuBar.add(menu);
frame.setJMenuBar(menuBar);
frame.pack();
frame.setVisible(true);
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
}
i have made JAVA code using Jmenulist and try to call it by actionlistener, but ActionListner is not working.Altough it is working in another code.bt it is creating problem in the program.
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
public class Submit {
public static void main(String[] args)
{
JFrame frame = new JFrame();
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("Graph");
JMenuItem closeMenuItem = new JMenu("Close");
closeMenuItem.addActionListener(new Close());
fileMenu.add(closeMenuItem);
menuBar.add(fileMenu);
frame.setJMenuBar(menuBar);
frame.setSize(500,500);
frame.setVisible(true);
}
}
class Close implements ActionListener {
public void actionPerformed(ActionEvent ev) {
System.out.println("Selected: ");
}}
When i complie it
public void actionPerformed(ActionEvent ev) {
System.out.println("Selected: ");
}
This section is not working. While Almost same code
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package in.ac.iiitd.cse201.rachit11084.hw3.q2;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
class MenuActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("Selected: " + e.getActionCommand());
}
}
public class ContructMenuActionListener {
public static void main(final String args[]) {
JFrame frame = new JFrame("MenuSample Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
fileMenu.setMnemonic(KeyEvent.VK_F);
menuBar.add(fileMenu);
JMenuItem newMenuItem = new JMenuItem("New");
newMenuItem.addActionListener(new MenuActionListener());
fileMenu.add(newMenuItem);
frame.setJMenuBar(menuBar);
frame.setSize(350, 250);
frame.setVisible(true);
}
}
Is working fine.
How should I solve this problem ?
Thanks.
JMenuItem closeMenuItem = new JMenuItem("Close");
not
JMenuItem closeMenuItem = new JMenu("Close");
The new JMenu creates a new sub-menu, so it cannot have an action associated, it only offers sub-menu items.
I am trying to implement this type of menu using Swing. Is there any off-the-shelf solution (free and/or commercial) yet?
Assuming you want that image on the menu, why not something like this?
BufferedImage image = ImageIO.read(url);
yourJMenu.setHorizontalTextPosition(SwingConstants.CENTER);
yourJMenu.setVerticalTextPosition(SwingConstants.BOTTOM);
yourJMenu.setIcon(new ImageIcon(image));
EDIT : Seems you're asking to start from scratch.
Please refer to: How to Use Menus before reading this answer.
EDIT 2 : Here is an SSCCE,
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.SwingConstants;
public class MenuTest {
public static void main(String[] argv) throws Exception {
// Create the menu bar
JMenuBar menuBar = new JMenuBar();
String imageURL = "http://blogs.discovermagazine.com/" +
"drone360/wp-content/themes/discoverblog/images/" +
"gear_icon.png";
// Create a menu
JMenu menu = new JMenu("Menu");
BufferedImage image = ImageIO.read(new URL(imageURL));
menu.setHorizontalTextPosition(SwingConstants.CENTER);
menu.setVerticalTextPosition(SwingConstants.BOTTOM);
menu.setIcon(new ImageIcon(image));
menuBar.add(menu);
// Create a menu item
JMenuItem item = new JMenuItem("Test Item");
menu.add(item);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setJMenuBar(menuBar);
frame.setSize(500, 550);
frame.setVisible(true);
}
}
Resource courtesy : http://pscode.org/media/
import java.awt.*;
import java.awt.event.*;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.ButtonGroup;
import javax.swing.JMenuBar;
import javax.swing.KeyStroke;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.JFrame;
/* MenuLookDemo.java requires images/middle.gif. */
/*
* This class exists solely to show you what menus look like.
* It has no menu-related event handling.
*/
public class MenuLookDemo {
JTextArea output;
JScrollPane scrollPane;
public JMenuBar createMenuBar() {
JMenuBar menuBar;
JMenu menu, submenu;
JMenuItem menuItem;
JRadioButtonMenuItemMenuItem;
JCheckBoxMenuItem cbMenuItem;
//Create the menu bar.
menuBar = new JMenuBar();
//Build the first menu.
menu = new JMenu("A Menu");
menu.setMnemonic(KeyEvent.VK_A);
menu.getAccessibleContext().setAccessibleDescription("The only menu in this program that has menu items");
menuBar.add(menu);
//a group of JMenuItems
menuItem = new JMenuItem("Av text-only menu item", KeyEvent.VK_T);
//menuItem.setMnemonic(KeyEvent.VK_T); //used constructor instead
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, ActionEvent.ALT_MASK));
menuItem.getAccessibleContext().setAccessibleDescription("This doesn't really do anything");
menu.add(menuItem);
ImageIcon icon = createImageIcon("middle.gif");
menuItem = new JMenuItem("Both text and icon", icon);
menuItem.setMnemonic(KeyEvent.VK_B);
menu.add(menuItem);
menuItem = new JMenuItem(icon);
menuItem.setMnemonic(KeyEvent.VK_D);
menu.add(menuItem);
//a group of radio button menu items
menu.addSeparator();
ButtonGroup group = new ButtonGroup();
rbMenuItem = new JRadioButtonMenuItem("A radio button menu item");
rbMenuItem.setSelected(true);
rbMenuItem.setMnemonic(KeyEvent.VK_R);
group.add(rbMenuItem);
menu.add(rbMenuItem);
rbMenuItem = new JRadioButtonMenuItem("Another one");
rbMenuItem.setMnemonic(KeyEvent.VK_O);
group.add(rbMenuItem);
menu.add(rbMenuItem);
//a group of check box menu items
menu.addSeparator();
cbMenuItem = new JCheckBoxMenuItem("A check box menu item");
cbMenuItem.setMnemonic(KeyEvent.VK_C);
menu.add(cbMenuItem);
cbMenuItem = new JCheckBoxMenuItem("Another one");
cbMenuItem.setMnemonic(KeyEvent.VK_H);
menu.add(cbMenuItem);
//a submenu
menu.addSeparator();
submenu = new JMenu("A submenu");
submenu.setMnemonic(KeyEvent.VK_S);
menuItem = new JMenuItem("An item in the submenu");
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, ActionEvent.ALT_MASK));
submenu.add(menuItem);
menuItem = new JMenuItem("Another item");
submenu.add(menuItem);
menu.add(submenu);
//Build second menu in the menu bar.
menu = new JMenu("Another Menu");
menu.setMnemonic(KeyEvent.VK_N);
menu.getAccessibleContext().setAccessibleDescription("This menu does nothing");
menuBar.add(menu);
return menuBar;
}
public Container createContentPane() {
//Create the content-pane-to-be.
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.setOpaque(true);
//Create a scrolled text area.
output = new JTextArea(5, 30);
output.setEditable(false);
scrollPane = new JScrollPane(output);
//Add the text area to the content pane.
contentPane.add(scrollPane, BorderLayout.CENTER);
return contentPane;
}
/** Returns an ImageIcon, or null if the path was invalid. */
protected static ImageIcon createImageIcon(String path) {
java.net.URL imgURL = MenuLookDemo.class.getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("MenuLookDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
MenuLookDemo demo = new MenuLookDemo();
frame.setJMenuBar(demo.createMenuBar());
frame.setContentPane(demo.createContentPane());
//Display the window.
frame.setSize(450, 260);
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}