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.
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.