Question

I'm having trouble getting my JMenuBar to appear alongside my paint() method.

package Main;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;

public class Main extends JFrame{

int x, y; // axis position for oval

//JMenuBar Variables
JMenuBar menuBar;
JMenu file;
JMenuItem newGame;
JMenuItem checkScore;
JMenuItem exitGame;

// DOUBLE BUFFERING
private Image dbImage;
private Graphics dbGraphics;

Font font = new Font("Arial", Font.ITALIC, 30);

// KeyListener Class
public class KeyListener extends KeyAdapter {
    public void keyPressed(KeyEvent e){
        int keyCode = e.getKeyCode();
        if(keyCode == e.VK_LEFT){
            if(x <=0){ // FRAME COLLISION DETECTION 
                x=0;
            }else
            x += -5; //decrement position to the left 
        }
        if(keyCode == e.VK_RIGHT){
            if(x >= 380){
                x = 380;
            }else
            x += +5; //incrementing position to the right
        }
        if(keyCode == e.VK_UP){
            if (y <= 25){
                y = 25;
            }else
            y += -5; //decrementing position up
        }
        if(keyCode == e.VK_DOWN){
            if(y >= 380){
                y = 380;
            }else
            y += +5; //incrementing position down
        }
    }
}


// CONSTRUCTOR
public Main(){
// Window Properties
    addKeyListener(new KeyListener()); // creates instance of KeyListener class
    setTitle("Tower Defence");
    setSize(400, 400);
    setResizable(false);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //setBackground(Color.CYAN);


// JMenuBar
    menuBar = new JMenuBar();
    file = new JMenu("File");
    newGame = new JMenuItem("New Game");
    checkScore = new JMenuItem("Check High Scores");
    exitGame = new JMenuItem("Close Game");

    menuBar.add(file);
    file.add(newGame);
    file.add(checkScore);
    file.addSeparator();
    file.add(exitGame);
    setJMenuBar(menuBar);

// Display frame after all components added
    setVisible(true);

// default position for oval
    x = 150;
    y = 150;

}


public void paint(Graphics g){
    dbImage = createImage(getWidth(), getHeight()); // creates image of screen
    dbGraphics = dbImage.getGraphics(); // gets graphics to be drawn in off screen image
    paintComponent(dbGraphics); // paints graphics
    g.drawImage(dbImage, 0, 0, this);  // draw image to the visible screen
}

    // PAINT GRAPHICS TO SCREEN
public void paintComponent(Graphics g){

    g.setFont(font);
    g.drawString("Hello World", 100, 200);

    g.setColor(Color.red);
    g.drawOval(x, y, 15, 15);
    g.fillOval(x, y, 15, 15);
    repaint();
}


// MAIN METHOD
public static void main(String[] args) {
    new Main();
}

}

I saw a different question where the solution was to override the paint method and add super.paint(g); when i tried this the JMenuBar appears but the frame keeps flickering constantly.

Was it helpful?

Solution

Heck, I'll throw my code in the ring. Recs as per my comments. Also, don't use KeyListeners but rather Key Bindings.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.RenderingHints;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.*;

@SuppressWarnings("serial")
public class Main2 extends JPanel {
   private static final int PREF_W = 400;
   private static final int PREF_H = PREF_W;
   private static final int OVAL_W = 15;
   private int x = 150;
   private int y = 150;
   private JMenuBar menuBar;
   private JMenu file;
   private JMenuItem newGame;
   private JMenuItem checkScore;
   private JMenuItem exitGame;
   private Font font = new Font("Arial", Font.ITALIC, 30);

   public Main2() {      
      menuBar = new JMenuBar();
      file = new JMenu("File");
      newGame = new JMenuItem("New Game");
      checkScore = new JMenuItem("Check High Scores");
      exitGame = new JMenuItem("Close Game");

      menuBar.add(file);
      file.add(newGame);
      file.add(checkScore);
      file.addSeparator();
      file.add(exitGame);

      addKeyBinding();
   }

   public JMenuBar getMenuBar() {
      return menuBar;
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
            RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, 
            RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
      g.setFont(font);
      g.drawString("Hello World", 100, 200);

      g.setColor(Color.red);
      g.drawOval(x, y, OVAL_W, OVAL_W);
      g.fillOval(x, y, OVAL_W, OVAL_W);
   }

   private void addKeyBinding() {
      int condition = WHEN_IN_FOCUSED_WINDOW;
      InputMap inputMap = getInputMap(condition);
      ActionMap actionMap = getActionMap();

      for (final MyDirection dir : MyDirection.values()) {
         KeyStroke keyStroke = KeyStroke.getKeyStroke(dir.getKeyCode(), 0);
         inputMap.put(keyStroke, dir.toString());
         actionMap.put(dir.toString(), new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent evt) {
               int newX = x + dir.getxTrans();
               int newY = y + dir.getyTrans();

               newX = Math.min(newX, PREF_W - 2 * OVAL_W);
               newX = Math.max(newX, OVAL_W);
               newY = Math.min(newY, PREF_H - 2 * OVAL_W);
               newY = Math.max(newY, OVAL_W);

               x = newX;
               y = newY;
               repaint();
            }
         });
      }
   }

   enum MyDirection {
      UP(KeyEvent.VK_UP, 0, -5), DOWN(KeyEvent.VK_DOWN, 0, 5), 
      LEFT(KeyEvent.VK_LEFT, -5, 0), RIGHT(KeyEvent.VK_RIGHT, 5, 0);

      private int keyCode;
      private int xTrans;
      private int yTrans;

      private MyDirection(int keyCode, int xTrans, int yTrans) {
         this.keyCode = keyCode;
         this.xTrans = xTrans;
         this.yTrans = yTrans;
      }

      public int getKeyCode() {
         return keyCode;
      }

      public int getxTrans() {
         return xTrans;
      }

      public int getyTrans() {
         return yTrans;
      }


   }

   private static void createAndShowGui() {
      Main2 main = new Main2();

      JFrame frame = new JFrame("Main2");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(main);
      frame.setJMenuBar(main.getMenuBar());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

OTHER TIPS

  • Dont extend JFrame unnecessarily

  • Dont overide any paint method of JFrame unnecessarily rathe add Jpanel and override paintComponent

  • Dont call repaint(...) in paintComponent(...) as this will cause a loop i.e repaint will re-call paintComponent and the cycle will carry on

  • Create and manipulate Swing components on Event Dispatch Thread

  • Dont call setSize(..) on JFrame rather override getPreferredSize and return an appropriate size which fits all drawings and than call JFrame#pack() before setting JFrame visible

  • Dont use KeyListener/KeyAdapter for Swing components rather use KeyBindings

Here is your code fixed:

enter image description here

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

public class Main extends JPanel {

    int x, y; // axis position for oval
    //JMenuBar Variables
    JMenuBar menuBar;
    JMenu file;
    JMenuItem newGame;
    JMenuItem checkScore;
    JMenuItem exitGame;
    Font font = new Font("Arial", Font.ITALIC, 30);

    // KeyBindings Class
    public class KeyBindings {

        public KeyBindings(final JComponent jc) {
            jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "Right");
            jc.getActionMap().put("Right", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent ae) {
                    if (x >= 380) {
                        x = 380;
                    } else {
                        x += +5; //incrementing position to the right
                    }
                    jc.repaint();

                }
            });

            jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "Left");
            jc.getActionMap().put("Left", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent ae) {
                    if (x <= 0) { // FRAME COLLISION DETECTION 
                        x = 0;
                    } else {
                        x += -5; //decrement position to the left 
                    }
                    jc.repaint();

                }
            });
            jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "Up");
            jc.getActionMap().put("Up", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent ae) {
                    if (y <= 25) {
                        y = 25;
                    } else {
                        y += -5; //decrementing position up
                    }
                    jc.repaint();

                }
            });
            jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "Down");
            jc.getActionMap().put("Down", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent ae) {
                    if (y >= 380) {
                        y = 380;
                    } else {
                        y += +5; //incrementing position down
                    }
                    jc.repaint();

                }
            });
        }
    }

    // CONSTRUCTOR
    public Main() {
        // Window Properties
        JFrame frame = new JFrame();
        frame.setTitle("Tower Defence");
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //setBackground(Color.CYAN);


        // JMenuBar
        menuBar = new JMenuBar();
        file = new JMenu("File");
        newGame = new JMenuItem("New Game");
        checkScore = new JMenuItem("Check High Scores");
        exitGame = new JMenuItem("Close Game");

        menuBar.add(file);
        file.add(newGame);
        file.add(checkScore);
        file.addSeparator();
        file.add(exitGame);

        JPanel panel = new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2 = (Graphics2D) g;
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

                g.setFont(font);
                g.drawString("Hello World", 100, 200);

                g.setColor(Color.red);
                g.drawOval(x, y, 15, 15);
                g.fillOval(x, y, 15, 15);
            }

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(400, 400);
            }
        };
        //add keybindings
        new KeyBindings(panel);

        frame.add(panel);

        frame.setJMenuBar(menuBar);

        frame.pack();
        // Display frame after all components added
        frame.setVisible(true);

        // default position for oval
        x = 150;
        y = 150;

    }

    // MAIN METHOD
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Main();
            }
        });
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top