简体   繁体   中英

Why won't my JMenuBar show up?

I'm trying to make a GUI in java, but JMenuBar has been giving me a hard time for two days. Can someone please tell me why it isn't showing up?

import java.awt.*;
import javax.swing.*;
import javax.swing.JPanel;
import java.awt.event.*;
import java.awt.image.*;     
import java.io.*;
import java.util.Arrays;
import javax.imageio.ImageIO;

public class selectionFrame extends JFrame
 {
  Font name;
  Font title;

  public void setup() //can't use constructer because this isn't given a size until after it is constructed.
  { 
   //getContentPane().add(menuBar);
   setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   getContentPane().setLayout(new FlowLayout());
   //getContentPane().add(j);

   setJMenuBar(createMenuBar());
   //getContentPane().add(createMenuBar());  
  }

  public JMenuBar createMenuBar()
  {
   JMenuBar menuBar;
   JMenu m_file;
   JMenuItem mi_save;
   JMenuItem mi_load;

   JMenu m_edit;
   JMenuItem mi_tileHeight;
   JMenuItem mi_tileWidth;

   menuBar = new JMenuBar();
   m_file = new JMenu("File");
   m_edit = new JMenu("Edit");

   mi_save = new JMenuItem("Save file", KeyEvent.VK_S);
   mi_load = new JMenuItem("Load file", KeyEvent.VK_L);
   mi_tileHeight = new JMenuItem("Set tile height", KeyEvent.VK_H);
   mi_tileWidth = new JMenuItem("Set tile width", KeyEvent.VK_W);

   menuBar.add(m_file);
   m_file.add(mi_save);
   m_file.add(mi_load);

   menuBar.add(m_edit);
   m_edit.add(mi_tileHeight);
   m_edit.add(mi_tileWidth);

   return menuBar;
  }

  public static void main(String[] args) //run
  { 
   selectionFrame sel = new selectionFrame();
   sel.setLocationRelativeTo(null);
   sel.setSize((int) 400 + (sel.getInsets().left + sel.getInsets().right),(int) 400  + (sel.getInsets().top + sel.getInsets().bottom));

   sel.setVisible(true);
   sel.setTitle("Tiles/Meta");
   sel.setResizable(false);
   sel.setFocusable(true);
   sel.getContentPane().setSize(sel.getSize());
   sel.setLocation((int) sel.getX() - (sel.getWidth()/2),(int) sel.getY() -  (sel.getHeight()/2));
   sel.setup();
   sel.repaint();

   } 
 }

You have an awful lot of extra code there.

 public class SelectionFrame extends JFrame { Font name; Font title; public SelectionFrame() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setJMenuBar(createMenuBar()); } public JMenuBar createMenuBar() { JMenuBar menuBar; JMenu m_file; JMenuItem mi_save; JMenuItem mi_load; JMenu m_edit; JMenuItem mi_tileHeight; JMenuItem mi_tileWidth; menuBar = new JMenuBar(); m_file = new JMenu("File"); m_edit = new JMenu("Edit"); mi_save = new JMenuItem("Save file", KeyEvent.VK_S); mi_load = new JMenuItem("Load file", KeyEvent.VK_L); mi_tileHeight = new JMenuItem("Set tile height", KeyEvent.VK_H); mi_tileWidth = new JMenuItem("Set tile width", KeyEvent.VK_W); menuBar.add(m_file); m_file.add(mi_save); m_file.add(mi_load); menuBar.add(m_edit); m_edit.add(mi_tileHeight); m_edit.add(mi_tileWidth); return menuBar; } public void main( String args[] ) { SelectionFrame sel = new SelectionFrame(); sel.setLocationRelativeTo(null); sel.setSize(400 + (sel.getInsets().left + > sel.getInsets().right), 400 + (sel.getInsets().top + sel.getInsets().bottom)); sel.setTitle("Tiles/Meta"); sel.setResizable(false); sel.setFocusable(true); sel.getContentPane().add( new JLabel( "Content", SwingConstants.CENTER), BorderLayout.CENTER ); sel.setLocation(sel.getX() - (sel.getWidth() / 2), sel.getY() - > (sel.getHeight() / 2)); sel.setVisible(true); } } 

That shows up with a menu bar and everything. if you add your content to the CENTER of the content pane (by default a border layout), the center automatically fills the whole content area, you don't have to resize anything.

This shows up as a window with a menu bar and everything works fine.

What platform are you doing this on? I'm on Vista, i get what i expect to see.

In my case I have tracked down a missing menu bar to a bug where I set the RootPane layout, tsk tsk. The RootPane (see eg http://download.java.net/jdk7/archive/b123/docs/api/javax/swing/JRootPane.html ) controls the layout of the menu bar, so when I changed its layout manager it lost the bar.

Instead, one should use the ContentPane to layout and add components to, eg:

frame.getContentPane().setLayout(...);
frame.getContentPane().add(...);

For future reference... this has nothing to do with the component being visible (as the OP said, the frame is visible but the menu bar is not), I have working code that sets the JMenuBar outside the constructor, and while being swing-thread-safe is Good Practice, it is not the cause of the problem.

What Java version are you using? Your menu bar shows up fine in 1.6.0_10 on my system. Try wrapping the body of your main method in an invokeLater() call so that it runs on the correct thread, like so:

public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                selectionFrame sel = new selectionFrame();
                sel.setLocationRelativeTo(null);
                sel.setSize((int) 400 + (sel.getInsets().left + sel.getInsets().right), 
                            (int) 400 + (sel.getInsets().top + sel.getInsets().bottom));
                sel.setTitle("Tiles/Meta");
                sel.setResizable(false);
                sel.setFocusable(true);
                sel.getContentPane().setSize(sel.getSize());
                sel.setLocation((int) sel.getX() - (sel.getWidth() / 2),
                                (int) sel.getY() - (sel.getHeight() / 2));
                sel.setup();
                sel.setVisible(true); // Follow Kendrick's advice too.
            }
        });
    }

Turns out you HAVE to set the JMenuBar inside the JFrame's constructor. I figured this out while looking at the differences between my code, and the marked answers code.

Thank you for your wonderful answer, John Gardner. Without you I would have most likely been stuck for months.

When I compile and run it, it shows up with a menu bar with file and edit menu items. Were you expecting more?

Also, capitalize your class- SelectionFrame

EDIT: One thing I forgot to look at, your code and every answer here is technically wrong. Often, it happens to work, but you are not allowed to do anything with Swing components unless you are in the AWT worker thread .

Normally you don't have to think about the worker thread much because every event that comes from your window will be on the worker thread anyway, but there is a tendency to forget about it when you construct your initial frame--and more often than not it just works anyway.

Sun used to recommend that you can work with components outside the AWT thread until the window has been realized (with either pack() or setVisible(true)) but this is no longer considered safe .

The easiest way to fix this might be for your main to create a swing worker thread before newing your SelectionFrame.

There is only a 50-50 chance this will fix your problem, but you should still take it into consideration whenever working on a GUI.

sel.setVisible(true);

Should be the last thing you call......

Also, just before the call to sel.setVisible(true); pls invoke sel.pack();

Pls note that instead of setSize it is better to use setPreferredSize , which is leveraged during frame packing.

Not directly relevant to your question, but still -- the use of a good layout manager is a huge time and frustration saviour when using Swing. MigLayout is simply an excellent one-stop layout manager.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM