How do I build a JMenu dynamically? - java

I am trying to build a JMenu dynamically right when clicking in it (I'm only getting an empty menu), below is my code.
final JMenu JMWindows = new JMenu("Opened Windows");
JMWindows.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for(JInternalFrame ji : desktop.getAllFrames())
{
JMWindows.add(ji.getTitle());
}
}
});
I've realized that the actionperformed is never called, the JMenu is inside a JMenuBar. What could be the problem ?

You add ActionListener to JMenu this cannot be done for JMenu use MenuListener and set it via JMenu#addMenuListener(..)
Also you need to call revalidate() and repaint() on JMenu instance after adding/removing components from it or the changes will not be reflected (we could also call this on the containers instance i.e JMenuBar or JFrame, but we know only 1 specific JMenu will change so no need IMO).
Please watch your variable naming schemes JMWindow should be jmWindow/jMWindow variables always begin with no caps and the 1st letter of every new word thereafter gets capitalized (besides for constants and enums).
Here is an example using MenuListener:
import java.awt.*;
import java.awt.event.*;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
public class Test {
private JDesktopPane jdpDesktop;
private static int openFrameCount = 0;
final JFrame frame = new JFrame("JInternalFrame Usage Demo");
public Test() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// A specialized layered pane to be used with JInternalFrames
jdpDesktop = new JDesktopPane() {
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
};
for (int i = 0; i < 3; i++) {
createFrame(); // Create first window
}
frame.setContentPane(jdpDesktop);
frame.setJMenuBar(createMenuBar());
// Make dragging faster by setting drag mode to Outline
jdpDesktop.putClientProperty("JDesktopPane.dragMode", "outline");
frame.pack();
frame.setVisible(true);
}
protected JMenuBar createMenuBar() {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Frame");
menu.setMnemonic(KeyEvent.VK_N);
JMenuItem menuItem = new JMenuItem("New IFrame");
menuItem.setMnemonic(KeyEvent.VK_N);
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
createFrame();
}
});
menu.add(menuItem);
menuBar.add(menu);
final JMenu jmWindows = new JMenu("Opened Windows");
jmWindows.addMenuListener(new MenuListener() {
#Override
public void menuSelected(MenuEvent me) {
jmWindows.removeAll();//remove previous opened window jmenuitems
for (JInternalFrame ji : jdpDesktop.getAllFrames()) {
JMenuItem menuItem = new JMenuItem(ji.getTitle());
jmWindows.add(menuItem);
}
jmWindows.revalidate();
jmWindows.repaint();
jmWindows.doClick();
}
#Override
public void menuDeselected(MenuEvent me) {
}
#Override
public void menuCanceled(MenuEvent me) {
}
});
menuBar.add(jmWindows);
return menuBar;
}
protected void createFrame() {
Test.MyInternalFrame frame = new Test.MyInternalFrame();
frame.setVisible(true);
// Every JInternalFrame must be added to content pane using JDesktopPane
jdpDesktop.add(frame);
try {
frame.setSelected(true);
} catch (java.beans.PropertyVetoException e) {
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
class MyInternalFrame extends JInternalFrame {
static final int xPosition = 30, yPosition = 30;
public MyInternalFrame() {
super("IFrame #" + (++openFrameCount), true, // resizable
true, // closable
true, // maximizable
true);// iconifiable
setSize(300, 300);
// Set the window's location.
setLocation(xPosition * openFrameCount, yPosition
* openFrameCount);
}
}
}

You need to repaint and or validate your frame after adding or removing something.
you can use the methods repaint() and validate() in your JFrame for this

You missed defining a JMenuItem.
final JMenu JMWindows = new JMenu("Opened Windows");
JMWindows.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for(JInternalFrame ji : desktop.getAllFrames())
{
JMenuItem menuItem = new JMenuItem(ji.getTitle());
JMWindows.add(menuItem);
}
}
});

Related

How to trigger an action when clicking a disabled JMenuItem?

I did a bit of googling and poking around in SO but all examples are find are for cases when the JMenuItem is enabled.
Context for what I'm trying to do is that I want my disabled JMenuItem (because of limited privileges), when clicked, to display a pop up box requesting that the user upgrade so that they can access said JMenuItem.
The following is a stripped down version of what I currently have, nothing got printed out on the command line:
public class ExportMenuItem extends JMenuItem
{
public ExportMenuItem()
{
super("Menu Item Name");
addMouseListener(new MouseAdapter()
{
#Override
public void mouseClicked(MouseEvent mouseEvent)
{
if (!isEnabled())
{
JOptionPane.showMessageDialog(editor.getFrame(), "Hello world.");
System.out.println("Sys print hello.");
}
System.out.println("Sys print hello outside.");
}
});
}
}
is this what you are looking for?
import javax.swing.*;
import java.awt.event.*;
public class ExportMenuItem extends JMenuItem{
public ExportMenuItem(){
super("menu item");
addMouseListener(new MouseListener(){
#Override
public void mouseClicked(MouseEvent mouseEvent){
if (!isEnabled()) {
JOptionPane.showMessageDialog(null, "Upgrade me!");
}//end of if
}//end of mouseClicked
public void mouseExited(MouseEvent mouseEvent){}
public void mouseEntered(MouseEvent mouseEvent){}
public void mouseReleased(MouseEvent mouseEvent){}
public void mousePressed(MouseEvent mouseEvent){}
// And the remaining methods to implement...
});//end of anonymous class
}//end of constructor
public static void main(String[] a){
JFrame f = new JFrame();
JMenu menu = new JMenu("menu");
JMenuBar menuBar = new JMenuBar();
f.setJMenuBar(menuBar);
f.setSize(300, 300);
f.setVisible(true);
menuBar.add(menu);
JMenuItem item = new ExportMenuItem();
menu.add(item);
item.setEnabled(false);
}//end of main
}//end of class
Maybe a complete different approach, that is more logical for users:
Place a describing text behind the menu item:
private void addRestartHint(JMenuItem m, String text) {
final String spaceholder = " ";
String t = m.getText() + spaceholder;
m.setLayout(new BorderLayout());
m.setText(t);
m.add(new JLabel(text), BorderLayout.EAST);
}

MyInternalFrame cannot be resolved to a type

Copied and pasted this code straight from Oracle's Java tutorial on making internal frames:
(Comments are Oracle's, not mine.) Marked error location w/comment "Error occurs here" in right margin. Computer says MyInternalFrame "cannot be resolved to type."
package components;
import javax.swing.JInternalFrame;
import javax.swing.JDesktopPane;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JMenuBar;
import javax.swing.JFrame;
import javax.swing.KeyStroke;
import java.awt.event.*;
import java.awt.*;
public class InternalFrameDemo extends JFrame
implements ActionListener {
JDesktopPane desktop;
public InternalFrameDemo() {
super("InternalFrameDemo");
//Make the big window be indented 50 pixels from each edge
//of the screen.
int inset = 50;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setBounds(inset, inset,
screenSize.width - inset*2,
screenSize.height - inset*2);
//Set up the GUI.
desktop = new JDesktopPane(); //a specialized layered pane
createFrame(); //create first "window"
setContentPane(desktop);
setJMenuBar(createMenuBar());
//Make dragging a little faster but perhaps uglier.
desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
}
protected JMenuBar createMenuBar() {
JMenuBar menuBar = new JMenuBar();
//Set up the lone menu.
JMenu menu = new JMenu("Document");
menu.setMnemonic(KeyEvent.VK_D);
menuBar.add(menu);
//Set up the first menu item.
JMenuItem menuItem = new JMenuItem("New");
menuItem.setMnemonic(KeyEvent.VK_N);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_N, ActionEvent.ALT_MASK));
menuItem.setActionCommand("new");
menuItem.addActionListener(this);
menu.add(menuItem);
//Set up the second menu item.
menuItem = new JMenuItem("Quit");
menuItem.setMnemonic(KeyEvent.VK_Q);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_Q, ActionEvent.ALT_MASK));
menuItem.setActionCommand("quit");
menuItem.addActionListener(this);
menu.add(menuItem);
return menuBar;
}
//React to menu selections.
public void actionPerformed(ActionEvent e) {
if ("new".equals(e.getActionCommand())) { //new
createFrame();
} else { //quit
quit();
}
}
//Create a new internal frame.
protected void createFrame() {
MyInternalFrame frame = new MyInternalFrame(); //Error occurs here//
frame.setVisible(true); //necessary as of 1.3
desktop.add(frame);
try {
frame.setSelected(true);
} catch (java.beans.PropertyVetoException e) {}
}
//Quit the application.
protected void quit() {
System.exit(0);
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
//Create and set up the window.
InternalFrameDemo frame = new InternalFrameDemo();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Display the window.
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();
}
});
}
}
From the comments of InternalFrameDemo.java:
/*
* InternalFrameDemo.java requires:
* MyInternalFrame.java
*/
it says that you need MyInternalFrame.java which is here. Add this file to your build path.

Adding a JMenu to a JPanel

I need to have a JMenu (the one with the arrow on right which can display JMenuItem) in a JPanel. The problem is that when I do that the JMenu is not activate on mouse rollover...
I don't know how to do that and if it's possible.
If you wrap your JMenu in a JMenuBar, it works as expected.
Here is a demo example:
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;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
public class TestMenus {
private JMenuBar createMenuBar(String name, int depth) {
JMenuBar bar = new JMenuBar();
bar.add(createMenu(name, depth));
return bar;
}
private JMenu createMenu(String name, int depth) {
JMenu menu = new JMenu(name);
for (int i = 0; i < 5; i++) {
if (depth > 0) {
menu.add(createMenu("sub-" + name, depth - 1));
}
}
for (int i = 0; i < 5; i++) {
menu.add(createMenuItem("Menu item " + (i + 1)));
}
return menu;
}
private JMenuItem createMenuItem(String name) {
final JMenuItem jMenuItem = new JMenuItem(name);
jMenuItem.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(jMenuItem, "Successfully pressed a menu item");
}
});
return jMenuItem;
}
protected void initUI() {
JFrame frame = new JFrame(TestMenus.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMenuBar("Root menu", 3));
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestMenus().initUI();
}
});
}
}
An the result:
Here is another way to solve this which I think is closer to what you want. It involves extending JMenuBar to give it the look of a JMenu Object.
The class contains a JMenu Object called menu. The add methods are overridden so you are adding to menu instead of the JMenuBar (You may have to override a few more add methods to make this perfect).
There are a few options with painting. I wasn't sure if you wanted the button style look of the JMenuBar, so I included a few comments on some options to customize that, as well as the underline look of the JMenuBar.
Here is the result of the button look with no border:
Here is the result with no button look and no border:
import java.awt.*;
import javax.swing.*;
public class JPanelMenu extends JMenuBar{
public static void main(String[] args) {
JFrame f = new JFrame("Menu Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenu jmenu = new JMenu("J Menu");
jmenu.add(new JMenuItem("Menu Item"));
JPanelMenu m = new JPanelMenu("Menu");
m.add(jmenu);
m.add(new JMenuItem("Menu Item 1"));
m.add(new JMenuItem("Menu Item 2"));
JPanel background = new JPanel();
background.add(m);
f.setContentPane(background);
f.pack();
f.setVisible(true);
}
//This is the JMenu that is shown
private JMenu menu;
public JPanelMenu(String title) {
super();
menu = new JMenu(title);
super.add(menu);
}
#Override
public Component add(Component comp) {
//You add the the JMenu instead of the JMenuBar
return menu.add(comp);
}
#Override
public JMenu add(JMenu c) {
//You add the the JMenu instead of the JMenuBar
return (JMenu) menu.add(c);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//Include these two lines to remove the button look
//Or remove this method to keep the button look
//g.setColor(getBackground());
//g.fillRect(0, 0, getWidth(), getHeight());
}
#Override
protected void paintBorder(Graphics g) {
//Remove this line to remove the underline look
//when you remove the button look
//An alternative is to you setBorderPainted(false);
//when you create the object or in the constructor
//Or remove this method to keep the border
//super.paintBorder(g);
}
}
You must pass a BorderLayout in JPanel layout then you can add menu bar in panel:
JPanel p = new JPanel();
p.setLayout(new BorderLayout());
p.add(menubar, BorderLayout.NORTH);

How to change jdesktoppane default background image?

How to change jdesktoppane background image in MDI (Multiple Documents interface) using java netbeans? Means I added the jdesktoppane to java MDI so now I want to change default background image of that jdesktoppane which I'm using in java MDI. Any easy way?
Check attached snapshot link may be you will better understand my question what I want.
http://i50.tinypic.com/iml1e9.jpg
+1 to MadProgrammers comment.
Simply override JDesktopPane paintComponent(..) and call drawImage(Image img,int x,int y,ImageObserver io) to draw an image.
Dont forget to honor the paint chain and call super.paintComponent(g) as first call in overridden paintComponent(..) method
Here is an example:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
public class JInternalFrameDemo {
private JDesktopPane jdpDesktop;
private static int openFrameCount = 0;
private BufferedImage img;
public JInternalFrameDemo() {
JFrame frame = new JFrame("JInternalFrame Usage Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
img = ImageIO.read(new URL("http://images1.wikia.nocookie.net/__cb20120817224359/villains/images/6/6a/Nine-Tailed_Fox_(Naruto).jpg"));
} catch (Exception ex) {
ex.printStackTrace();
}
// A specialized layered pane to be used with JInternalFrames
jdpDesktop = new JDesktopPane() {
#Override
protected void paintComponent(Graphics grphcs) {
super.paintComponent(grphcs);
grphcs.drawImage(img, 0, 0, null);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(img.getWidth(), img.getHeight());
}
};
createFrame(); // Create first window
frame.setContentPane(jdpDesktop);
frame.setJMenuBar(createMenuBar());
// Make dragging faster by setting drag mode to Outline
jdpDesktop.putClientProperty("JDesktopPane.dragMode", "outline");
frame.pack();
frame.setVisible(true);
}
protected JMenuBar createMenuBar() {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Frame");
menu.setMnemonic(KeyEvent.VK_N);
JMenuItem menuItem = new JMenuItem("New IFrame");
menuItem.setMnemonic(KeyEvent.VK_N);
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
createFrame();
}
});
menu.add(menuItem);
menuBar.add(menu);
return menuBar;
}
protected void createFrame() {
MyInternalFrame frame = new MyInternalFrame();
frame.setVisible(true);
// Every JInternalFrame must be added to content pane using JDesktopPane
jdpDesktop.add(frame);
try {
frame.setSelected(true);
} catch (java.beans.PropertyVetoException e) {
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new JInternalFrameDemo();
}
});
}
class MyInternalFrame extends JInternalFrame {
static final int xPosition = 30, yPosition = 30;
public MyInternalFrame() {
super("IFrame #" + (++openFrameCount), true, // resizable
true, // closable
true, // maximizable
true);// iconifiable
setSize(300, 300);
// Set the window's location.
setLocation(xPosition * openFrameCount, yPosition
* openFrameCount);
}
}
}
I resolve it in a separate function to create a desktop object.
Code as below
private JDesktopPane intializeDesktop(JDesktopPane mydesktop,String imagePath,int scalx,int scaly) {
// A specialized layered pane to be used with JInternalFrames
mydesktop = new JDesktopPane() {
ImageIcon icon = new ImageIcon(imagePath);
Image image = icon.getImage();
Image newimage = image.getScaledInstance(scalx, scaly, Image.SCALE_SMOOTH);
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(newimage, 0, 0, this);
}
};
return mydesktop;
}

Example Program JMenubar on JInternalFrame when i Maximize the JInternalFrame

Hi I need an Example program in which
When i maximize the JInternalFrame the JMenuBar of JFrame should set on JInternalFrame
and When i minimize the JInternalFrame again the JMenuBar should leave JinternalFrame and set
to JFrame as shown below
Please provide me an Example Program in Java Swing
Seems to work fine, please post SSCCE to show specific problem:
import java.awt.*;
import java.awt.event.*;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
public class JInternalFrameDemo {
JDesktopPane jdpDesktop;
static int openFrameCount = 0;
public JInternalFrameDemo() {
JFrame frame = new JFrame("JInternalFrame Usage Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// A specialized layered pane to be used with JInternalFrames
jdpDesktop = new JDesktopPane() {
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 600);
}
};
createFrame(); // Create first window
frame.setContentPane(jdpDesktop);
frame.setJMenuBar(createMenuBar());
// Make dragging faster by setting drag mode to Outline
jdpDesktop.putClientProperty("JDesktopPane.dragMode", "outline");
frame.pack();
frame.setVisible(true);
}
protected JMenuBar createMenuBar() {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Frame");
menu.setMnemonic(KeyEvent.VK_N);
JMenuItem menuItem = new JMenuItem("New IFrame");
menuItem.setMnemonic(KeyEvent.VK_N);
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
createFrame();
}
});
menu.add(menuItem);
menuBar.add(menu);
return menuBar;
}
protected void createFrame() {
MyInternalFrame frame = new MyInternalFrame();
frame.setVisible(true);
// Every JInternalFrame must be added to content pane using JDesktopPane
jdpDesktop.add(frame);
try {
frame.setSelected(true);
} catch (java.beans.PropertyVetoException e) {
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new JInternalFrameDemo();
}
});
}
class MyInternalFrame extends JInternalFrame {
static final int xPosition = 30, yPosition = 30;
public MyInternalFrame() {
super("IFrame #" + (++openFrameCount), true, // resizable
true, // closable
true, // maximizable
true);// iconifiable
setSize(300, 300);
// Set the window's location.
setLocation(xPosition * openFrameCount, yPosition
* openFrameCount);
}
}
}
I also have similar problem. It is a bug in JInternalFrame LookAndFell. JInternalFrames using Windows L&F, should be
more Windows like. If I maximize a JInternalWindow,
that window is not working as in Windows.
Its top bar should be one with the MDI.
Meus and Toolbars should be inside.
Maximized Internal frames should not have their
own border.
Visit
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4102061
for datails.

Categories

Resources