Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 9 of 9
  1. #1
    Regular Coder xconspirisist's Avatar
    Join Date
    Jun 2006
    Location
    Great Britain.
    Posts
    138
    Thanks
    1
    Thanked 6 Times in 6 Posts

    Reusing JMenuItems

    Hey folks, I have a somewhat silly issue with JMenuItems. Really simple - I want to add one JMenuItem to two different JMenus, but swing only pops it on a menu onces, irrespective of how many times I add it. It would be pretty handy to reuse the JMenuItems, so I can pop them on context menus and whatnot.

    Has anyone heard of this issue before? I have even read some swing documentation, but no joy.

    Many thanks in advance for anyone who has the time to answer
    If I have been helpful, use the "thank" button - It makes me happy!

    xconspirisist.co.uk - homepage of my online alias
    technowax.net - a community for people interested in all forms of modern technology.

  • #2
    Regular Coder brad211987's Avatar
    Join Date
    Sep 2005
    Location
    Ohio
    Posts
    631
    Thanks
    10
    Thanked 50 Times in 50 Posts
    Post the code you are using. It seems like you should be able to reuse them without much trouble.

  • #3
    Regular Coder xconspirisist's Avatar
    Join Date
    Jun 2006
    Location
    Great Britain.
    Posts
    138
    Thanks
    1
    Thanked 6 Times in 6 Posts
    Well, functionally it is nothing more than the following:

    Code:
    import javax.swing.JFrame;
    import javax.swing.JMenu;
    import javax.swing.JMenuItem;
    import javax.swing.JMenuBar;
    
    class Foo extends JFrame {
    	public Foo() {
    		this.setTitle("foo");
    		this.setBounds(100, 100, 640, 480); 
    		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    		this.setupComponents(); 
    
    		this.setVisible(true);
    		this.setLocationRelativeTo(null);
    	}
    
    	private final JMenuBar mb = new JMenuBar();
    
    	private void setupComponents() {
    		this.mb.add(this.getMenuFile());
    		this.setJMenuBar(this.mb);
    	}
    
    	private JMenu getMenuFile() {
    		JMenu mnuFile = new JMenu("File");	
    		JMenuItem mniSomething = new JMenuItem("Something");
    		mnuFile.add(mniSomething);
    		mnuFile.add(mniSomething);
    		mnuFile.add(mniSomething);
    
    		mnuFile.addSeparator();
    		mnuFile.add(new JMenuItem("Exit"));
    		
    		return mnuFile;
    	}
    
    	public static final void main(String[] args) {
    		new Foo();
    	}
    }
    That test case prooves my point though. Lines 28 - 30 attempt to add mniSomething to the menu several times, yet running it - the item only appears once. If you expand the test case to use two JMenu's (edit menu, for example), then try to add mniSomething to it, then the first instance on the file menu is removed.

    I hope that makes sense! I just want to reuse my JMenuItems
    If I have been helpful, use the "thank" button - It makes me happy!

    xconspirisist.co.uk - homepage of my online alias
    technowax.net - a community for people interested in all forms of modern technology.

  • #4
    Regular Coder brad211987's Avatar
    Join Date
    Sep 2005
    Location
    Ohio
    Posts
    631
    Thanks
    10
    Thanked 50 Times in 50 Posts
    I'll admit, I've never run into this one. Admittedly I don't do a lot with Swing anymore, but this is a bit strange to me.

    I would probably just create them on the fly as you are doing with the Exit option, not seeing any thing else that sticks out immediately at me.

  • #5
    Regular Coder xconspirisist's Avatar
    Join Date
    Jun 2006
    Location
    Great Britain.
    Posts
    138
    Thanks
    1
    Thanked 6 Times in 6 Posts
    That is not really a viable solution, I was looking for the real cause behind this.
    If I have been helpful, use the "thank" button - It makes me happy!

    xconspirisist.co.uk - homepage of my online alias
    technowax.net - a community for people interested in all forms of modern technology.

  • #6
    Regular Coder brad211987's Avatar
    Join Date
    Sep 2005
    Location
    Ohio
    Posts
    631
    Thanks
    10
    Thanked 50 Times in 50 Posts
    I can't find any other information on it, seems like a design decision to me. Curious though, what is not viable about creating them as you add them?

  • #7
    Senior Coder TheShaner's Avatar
    Join Date
    Sep 2005
    Location
    Orlando, FL
    Posts
    1,126
    Thanks
    2
    Thanked 40 Times in 40 Posts
    Well, what you are doing essentially is attempting to add the same instance of a JMenuItem to a component, which won't work since it sees that the JMenuItem instance already exists within it. A component cannot contain more than one of the exact same instances of another component. This is not just a JMenu issue; this is true for all components.

    Try this:
    Code:
    public class Test
    {
        public static void main(String args[])
        {
            JPanel panel = new JPanel();
            JButton newBtn = new JButton("Test");
    
            panel.add(newBtn);
            panel.add(newBtn);
            panel.add(newBtn);
    
            System.out.println("# of Buttons: " + panel.getComponentCount());
        }
    }
    If you run the above, you'll get an answer of 1.

    What you can do is clone the menu item. You'll have to create your own clone function (since I don't believe the clone() method has been implemented for JMenuItem).

    So you may have to do something like:
    Code:
    private static JMenuItem cloneMenuItem(JMenuItem mi)
    {
        JMenuItem newMi = new JMenuItem(mi.getText());
    
        return newMi;
    }
    You would expand this clone function to do "sets" on the new menu item and populate the set methods with "gets" from the passed in menu item.

    The calling of this function may look like this:
    Code:
    JMenuItem item = new JMenuItem("Item");
    menu.add(item);
    menu.add(cloneMenuItem(item));
    menu.add(cloneMenuItem(item));
    Something to think about is that container components like JMenu provide methods to access the components contained within them just by referencing their instances. This would not be possible if the container components allowed multiple duplicate instances within them. Looping through their components to do stuff like updates and paints would become heavily convoluted with multiple duplicate instances.

    -Shane
    Last edited by TheShaner; 06-30-2010 at 03:19 PM.

  • #8
    Senior Coder TheShaner's Avatar
    Join Date
    Sep 2005
    Location
    Orlando, FL
    Posts
    1,126
    Thanks
    2
    Thanked 40 Times in 40 Posts
    Another fun exercise in understanding components versus other objects, such as Collections and Lists:
    Code:
    public class Test
    {
        public static void main(String args[])
        {
            ArrayList<JMenuItem> test = new ArrayList<JMenuItem>();
    
            JMenuItem item = new JMenuItem("Item");
    
            test.add(item);
            test.add(item);
            test.add(item);
    
            System.out.println("Size: " + test.size() + "\nContents: " + test.toString());
    
            item.setText("Testing");
    
            System.out.println("Size: " + test.size() + "\nContents: " + test.toString());
    
            test.remove(item);
    
            System.out.println("Size: " + test.size() + "\nContents: " + test.toString());
        }
    }
    You'll see that the setting of the text of course affects all three instances returned by the toString() method of the List since it's the same instance in the List.

    The remove method for a List just removes the first occurrence of the instance in the list. Collections and Lists are made to handle multiple duplicate instances. Components are not since they work entirely different.

    -Shane

  • #9
    New to the CF scene
    Join Date
    Jan 2011
    Posts
    1
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Hi yeah this is funky. Thanks.

    Here is an example of switching the same item to different menus on popup:

    Code:
    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 AddTest {
    
        public static void main(String[] args) {
            JFrame frame = new JFrame();
            frame.setLayout(new BorderLayout());
    
            final JMenuItem item = new JMenuItem("Shared item");
            item.setBackground(new java.awt.Color(220, 169, 117));
            item.addActionListener(
                    new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                            System.out.println("Item clicked hashcode: " + item.hashCode());
                        }
                    });
    
            MyMenu m1 = new MyMenu("One", item);
            MyMenu m2 = new MyMenu("Two", item);
            m2.add(new JMenuItem("Unmoving item on menu two"));
            MyMenu m3 = new MyMenu("Three", item);
    
    //  Item not added yet.
    //        m1.add(item);
    //        m2.add(item);
    //        m3.add(item);
    
            JMenuBar mBar = new JMenuBar();
            mBar.add(m1);
            mBar.add(m2);
            mBar.add(m3);
    
            frame.add(mBar, BorderLayout.NORTH);
            frame.setBounds(0, 0, 300, 200);
            frame.setVisible(true);
        }
    }
    
    class MyMenu extends JMenu {
    
        JMenuItem sharedItem;
    
        public MyMenu(String text, JMenuItem shared) {
            super(text);
            sharedItem = shared;
        }
    
        @Override
        public void setPopupMenuVisible(boolean b) {
            add(sharedItem);
            super.setPopupMenuVisible(b);
        }
    }


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •