-1

I need to display a Java JMenu opening upwards instead of downwards.

I am creating an application made of a series of JFames. One of those JFrames hosts a JMenuBar, built by a series of JMenu instances, and given the size and the position of this JFrame, it is at the bottom of the application.

The application runs in a high resolution display shared with other applications, and it is placed at the top position of it.

So using the default settings of JMenu causes the menu opening downwards overlapping the others applications areas running on the bottom of the screen.

Can anyone help me in finding the correct way for forcing the menu opening upwards please?

I tried using the setLocation() method of the JMenu class, I was expecting the menu open at the coordinates I gave, but it did not work. I also investigated at the BoxLayout features, but it did not help.

Morriz
  • 3
  • 2
  • I'm confused. A `JToolBar` can be placed anywhere on your `JFrame`. A `JMenuBar` must be placed at the top of the `JFrame`. – Gilbert Le Blanc Feb 09 '23 at 17:52
  • 1
    In case you are using a `JPopupMenu` there is a `show` method of it, accepting the location as parameter. [The tutorial](https://docs.oracle.com/javase/tutorial/uiswing/components/menu.html#popup) can get you started. @GilbertLeBlanc the same tutorial shows that you can add a `JMenuBar` as a regular `Component` inside the frame's content pane (on `BorderLayout.LINE_START`) at least (see [MenuLayoutDemo](https://docs.oracle.com/javase/tutorial/uiswing/examples/components/MenuLayoutDemoProject/src/components/MenuLayoutDemo.java)) – gthanop Feb 09 '23 at 19:07
  • @gthanop: Just because you can add a `JMenuBar` as a regular component, doesn't mean you should. – Gilbert Le Blanc Feb 09 '23 at 20:34
  • Please provide enough code so others can better understand or reproduce the problem. – Community Feb 09 '23 at 23:26

1 Answers1

0

You can use a MenuListener to reset the location of the popup menu to display above the menu:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class MenuPopupUpListener implements MenuListener
{
    @Override
    public void menuSelected(MenuEvent e)
    {
        SwingUtilities.invokeLater(() ->
        {
            JMenu menu = (JMenu)e.getSource();
            JPopupMenu popup = menu.getPopupMenu();

            Rectangle bounds = popup.getBounds();
            Point location = menu.getLocationOnScreen();

            location.y -= bounds.getHeight();
            popup.setLocation(location);
        });
    }

    @Override
    public void menuCanceled(MenuEvent e) {}

    @Override
    public void menuDeselected(MenuEvent e) {}

    private static void createAndShowGUI()
    {
        JMenuBar menuBar = new JMenuBar();
        JMenu menu = new JMenu("Menu 1");
        menuBar.add( menu );

        menu.add( new JMenuItem( "MenuItem 1a" ) );
        menu.add( new JMenuItem( "MenuItem 1b" ) );
        menu.add( new JMenuItem( "MenuItem 1c" ) );

        //  Add a listener to all menus to have the popup open above the menu

        MenuListener ml = new MenuPopupUpListener();
        menu.addMenuListener( ml );

        JFrame frame = new JFrame("MenuPopupUp");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(menuBar, BorderLayout.PAGE_END);
        frame.setLocationByPlatform( true );
        frame.setSize(300, 300);
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
    }
}

The listener would need to be added to all menus.

camickr
  • 321,443
  • 19
  • 166
  • 288