Search code examples
javaclickmenubarchildwindowmainwindow

Java Already opened windows inside the Content pane of Main window goes beneath the main window when a menu item is clicked on the main window


I am a beginner in java swing an this is my first question. Before asking this I have searched long and not found any solution.

I have a main window with JmenuBar and MenuItems. My problem is that when I click on a menu item the already opened window is going beneath the main Window and new window popup on the top of the main widow.

My requirements

  1. When I click on a menu item the opened new window should be on the top of the previously opened window and and both windows should be over the main window.
  2. When I click again on menu at this position the drop down menu items should be over all the windows.

I have tried setAlwaysOnTop(true); to all the menu item windows. but it fails to meet my requirement (2.)

Please help me

Here is my code for main window

public class Main extends JFrame {
    private JPanel contentPane;
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Main frame = new Main();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    public Main() {
        setTitle("Menu");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(500, 500, 400, 425);
        setLocationRelativeTo(null);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(null);
        
        JMenuBar menuBar = new JMenuBar();
        setJMenuBar(menuBar);
        
        JMenu mnPurchase = new JMenu("Purchase");
        menuBar.add(mnPurchase);
        
        JMenuItem mntmAddPurchaseInvoice = new JMenuItem("Purchase Invoice");
        mntmAddPurchaseInvoice.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Purchase frame = new Purchase();
                frame.setVisible(true);
                
                }
            });
        mnPurchase.add(mntmAddPurchaseInvoice);
        
        JMenu mnSales = new JMenu("Sales");
        menuBar.add(mnSales);
        
        JMenuItem mntmProcessSale = new JMenuItem("Generate Sales Invoice");
        mntmProcessSale.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Sale frame = new Sale();
                frame.setVisible(true);
            }
        });
        mnSales.add(mntmProcessSale);
    }
    
    public class Purchase extends JFrame {
    public void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Purchase frame = new Purchase();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    public Purchase() {
        setTitle("Purchase");
        setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        setBounds(500, 500, 300, 300);
        setLocationRelativeTo(null);
        contentPane = new JPanel();
        setContentPane(contentPane);
        }
    }   
    
    public class Sale extends JFrame {
    public void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Sale frame = new Sale();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    public Sale() {
        setTitle("Sale");
        setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        setBounds(500, 500, 300, 300);
        setLocationRelativeTo(null);
        contentPane = new JPanel();
        setContentPane(contentPane);
            }
        }
    }

Solution

  • This is a pretty trivial fix: Use a JDialog instead of a JFrame for your 'child' frames.

    public class Sale extends JDialog {
        public Sale(JFrame owner) {
            super(owner);
            setTitle("Sale");
            setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
            setBounds(500, 500, 300, 300);
            setLocationRelativeTo(null);
            contentPane = new JPanel();
            setContentPane(contentPane);
        }
    }
    

    I did that for both, Sale and Purchase and it seemed to work as described. I also had to change the action listener code.

    mntmProcessSale.addActionListener( e -> {
                Sale frame = new Sale(this);
                frame.setVisible(true);
            });
    

    I switched from an anonymous class to a lambda for the syntax of using this instead of the alternative Main.this notation.