【问题标题】:JMenuBar not appearing unless I put everything in a single class除非我将所有内容放在一个类中,否则 JMenuBar 不会出现
【发布时间】:2018-09-10 01:54:32
【问题描述】:

我正在尝试使用 MenuBar 制作框架,但无法显示。我尝试使用pack(),因为它在类似问题中被建议,但这使得我的框架不存在,我最终只得到了上部窗口栏。

如果我将所有内容放在一个类中,它就可以工作;所以我认为我的问题是关于 Java 结构的基本问题。

这是我的 JMenuBar 类:

package jpaintnet;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;

public class JMenuBar extends JFrame implements MenuListener, ActionListener {

    JMenuBar mb;
    JMenu addImage, addObject, save;
    JMenuItem circle, rectangle, triangle, line;

    public JMenuBar() {

        mb = new JMenuBar();

        addObject = new JMenu("Add Object");
        mb.add(addObject);

        addImage = new JMenu("Add a new image");
        mb.add(addImage);

        save = new JMenu("save");
        mb.add(save);


        circle = new JMenuItem("Create a circle");
        circle.addActionListener(this);
        addObject.add(circle);

        rectangle = new JMenuItem("Create a rectangle");
        rectangle.addActionListener(this);
        addObject.add(rectangle);

        triangle = new JMenuItem("Create a triangle");
        triangle.addActionListener(this);
        addObject.add(triangle);

        line = new JMenuItem("Create a line");
        line.addActionListener(this);
        addObject.add(line);
    }



    @Override
    public void actionPerformed(ActionEvent e) {
       //here goes everything!
    }

    @Override
    public void menuSelected(MenuEvent e) {
    }

    @Override
    public void menuDeselected(MenuEvent e) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void menuCanceled(MenuEvent e) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }
}

我的 JFrame 类:

package jpaintnet;

import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import java.awt.HeadlessException;
import javax.swing.JMenuBar;
import javax.swing.JPanel;

public class Frame extends JFrame
{

    public Frame(String title) throws HeadlessException {

        JMenuBar mb = new JMenuBar();
        JPanel panel = new JPanel();

        this.setBounds(100,100,640,480);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setBackground(Color.white);

        this.getContentPane().add(BorderLayout.SOUTH, panel);
        this.getContentPane().add(BorderLayout.NORTH, mb);

        this.setVisible(true);
    }
}

最后,我的主要内容:

package jpaintnet;

public class Main {

    public static void main(String[] args) {

        Frame f = new Frame("JPaintNet");
        f.setVisible(true);
    }
}

我已经评论了setVisible()methods 之一,但我最终还是把它放在这里以防万一。

提前谢谢你。

【问题讨论】:

  • 您正在使用导入 javax.swing.JMenuBar 并创建自己的名为 JMenuBar 的类。你不应该使用重复的类名。如果你想要一个定制的 JMenuBar,你应该扩展它并在那里添加额外的特性。此外,您不需要一开始就为 JMenuBar 创建一个新类来向它添加项目;所有这些都可以在框架类中的 JMenuBar 对象上调用。
  • public class JMenuBar extends JFrame ????好吧,这是一个错误的开始。你看过How to Use Menus的例子吗?菜单栏属于单个框架,其余内容应位于该框架内
  • @faris,非常感谢!我再也不会那样做了。你真的帮了我:)。
  • @ClaudiaProvoste 请接受最能帮助您解决问题的答案。它可以帮助未来的读者。如果答案没有帮助,请将 cmets 留在他们下方。所以发布者可以相应地更新它们。

标签: java swing jframe jmenubar


【解决方案1】:

你犯了几个错误。

  1. 在您的 Frame 类中删除以下导入

    import javax.swing.JMenuBar;
    

    因为一旦你导入了swing.JMenuBar,jvm 就会忽略你创建的JMenuBar

  2. 您的JMenuBar 类应该从javax.swing.JMenuBar 扩展,而不是从JFrame

    public class JMenuBar extends javax.swing.JMenuBar implements MenuListener, ActionListener
    
  3. 去掉 mb = new JMenuBar(); 构造函数中的 mb = new JMenuBar(); 语句。因为当您创建new JMenuBar() 时,jvm 所做的第一件事就是调用它的构造函数。在构造函数中创建另一个new JMenuBar() 意味着您会不断创建这么多JMenuBars,这最终会导致StackOverFlow 错误。

  4. 删除JMenuBar 类中的变量mb 并替换为this

    this.add(addObject);
    this.add(addImage);
    this.add(save);
    

那么你的窗口应该可以正常工作了。


更新:

作为MadProgrammer has suggested,请记住让您的类名独一无二,尤其是在涉及由 java 开发的库时。这里有一个额外的提示,在创建数据库时避免使用 java 关键字作为表名或列名。如果你以后要使用hibernate这样的框架,它会为你省去很多痛苦。

【讨论】:

  • 尽可能不要重复使用现有的类名,这只是令人困惑(是的,我知道 OP 做到了,所以让他们停止)
【解决方案2】:

@Andrew,已更新您的代码,如下所示供您参考。参考内联 cmets:

这是您的 MyMenuBar,即 JMenuBar 类:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;

/*
 * 1. Renamed your class "JMenuBar" to "MyMenuBar" - do not use Java class names. Its bad practice
 * 2. Extend from JMenuBar class to create Menu Bar. Whereas JFrame requires to create a frame
 */
public class MyMenuBar extends JMenuBar implements MenuListener, ActionListener { 
  JMenu addImage, addObject, save;
  JMenuItem circle, rectangle, triangle, line;

  public MyMenuBar() {


      addObject = new JMenu("Add Object");
      add(addObject);

      addImage = new JMenu("Add a new image");
      add(addImage);

      save = new JMenu("save");
      add(save);


      circle = new JMenuItem("Create a circle");
      circle.addActionListener(this);
      addObject.add(circle);

      rectangle = new JMenuItem("Create a rectangle");
      rectangle.addActionListener(this);
      addObject.add(rectangle);

      triangle = new JMenuItem("Create a triangle");
      triangle.addActionListener(this);
      addObject.add(triangle);

      line = new JMenuItem("Create a line");
      line.addActionListener(this);
      addObject.add(line);
  }



  @Override
  public void actionPerformed(ActionEvent e) {
     //here goes everything!
  }

  @Override
  public void menuSelected(MenuEvent e) {
  }

  @Override
  public void menuDeselected(MenuEvent e) {
      throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
  }

  @Override
  public void menuCanceled(MenuEvent e) {
      throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
  }
}

这是您的 MyFrame,即 Frame 类:

    import java.awt.BorderLayout;
import java.awt.Color;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class MyFrame
  extends
  JFrame {

  public MyFrame( String title ) {
    MyMenuBar mb = new MyMenuBar();
    JPanel panel = new JPanel();

    this.setBounds( 100, 100, 640, 480 );
    this.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    this.setBackground( Color.white );

    this.getContentPane().add( BorderLayout.SOUTH, panel );
    // this.getContentPane().add( BorderLayout.NORTH, mb ); //Do not use this
    // method to set menu bar
    this.setJMenuBar( mb ); // this is ideal method to set menu bar

    this.setTitle( title ); // Missing as you have supplied title but missed to set it to frame
    this.setVisible( true );
  }

  // added main method here from your Main class
  public static void main( String[] args ) {

    MyFrame f = new MyFrame( "JPaintNet" );
    f.setVisible( true );
  }
}

将创建如下窗口:

我认为这就是你想要的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-05
    • 1970-01-01
    相关资源
    最近更新 更多