I'm having this weird thing where a JMenuBar shows up in both my JFrame and JPanel. I have no idea how this is happening. I'm not really sure if its because the menu bar and the JPanel are in different classes or could be from the observer pattern.
What it looks like when I run it.
JFrame code
package model;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
public class TetrisGUI extends JFrame implements Observer {
/**
*
*/
private static final long serialVersionUID = -2900288878430508454L;
private final Board myBoard;
private final TetrisMenu myMenu;
private final TetrisBoardPanel myGamePanel;
public TetrisGUI() {
super("Tetris");
myBoard = new Board();
myMenu = new TetrisMenu();
myGamePanel = new TetrisBoardPanel();
this.setJMenuBar(myMenu.getMenuBar());
}
public void start() {
add(myGamePanel.getGamePanel());
this.pack();
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.pack();
}
public JMenuBar createMenu() {
JMenuBar menubar = new JMenuBar();
menubar.add(new JMenu("Game"));
return menubar;
}
@Override
public void update(Observable o, Object arg) {
// TODO Auto-generated method stub
}
JPanel code
package model;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JPanel;
import javax.swing.Timer;
public class TetrisBoardPanel extends JPanel implements Observer {
/**
* auto generated SID.
*/
private static final long serialVersionUID = 5916557959811294203L;
private final Board myBoard;
private Block[][] myBlocks;
private final Timer myTimer;
private Color myBlockColor;
public TetrisBoardPanel() {
myBoard = new Board();
myBoard.addObserver(this);
this.setPreferredSize(new Dimension(300,658));
System.out.println(myBlocks);
myTimer = new Timer(1000, timeAction());
myBoard.newGame();
myTimer.start();
}
@Override
protected void paintComponent(Graphics g) {
if (myBlocks == null) {
for (int j = 3; j < 280; j+=30) {
for (int i = 28; i < 600; i+=30) {
g.fillRect(j, i, 30, 30);
}
}
} else {
int x = 3;
int y = 28;
for (int i = 20; i > -1; i--) {
for (int j=0; j<myBlocks[i].length; j++) {
if (myBlocks[i][j] == null) {
g.setColor(Color.BLACK);
g.fillRect(x, y, 30, 30);
} else {
if (myBlocks[i][j].equals(Block.I)) {
myBlockColor = Color.ORANGE;
} else if (myBlocks[i][j].equals(Block.J)) {
myBlockColor = Color.CYAN;
} else if (myBlocks[i][j].equals(Block.L)) {
myBlockColor = Color.RED;
} else if (myBlocks[i][j].equals(Block.O)) {
myBlockColor = Color.PINK;
} else if (myBlocks[i][j].equals(Block.S)) {
myBlockColor = Color.MAGENTA;
} else if (myBlocks[i][j].equals(Block.T)) {
myBlockColor = Color.GREEN;
} else if (myBlocks[i][j].equals(Block.Z)) {
myBlockColor = Color.LIGHT_GRAY;
}
g.setColor(myBlockColor);
g.fillRect(x, y, 30, 30);
g.setColor(Color.white);
g.fillRect(x+7,y+7,17,17);
}
x += 30;
}
x = 3;
y += 30;
}
}
repaint();
}
public ActionListener timeAction() {
ActionListener task = new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
myBoard.step();
}
};
return task;
}
@Override
public void update(Observable theOb, Object theArg) {
if (theArg instanceof Block[][]) {
myBlocks = (Block[][]) theArg;
System.out.println(((Block[][]) theArg).length);
for (final Block[] row : (Block[][])theArg) {
for (final Block b : row) {
if (b == null) {
System.out.print("[ ]");
} else {
System.out.print("[" + b +"]");
}
}
System.out.println();
}
}
}
public JPanel getGamePanel() {
JPanel pan = new JPanel();
pan.add(this);
return pan;
}
Menu bar code
package model;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
public class TetrisMenu {
private final JMenuBar myMenuBar;
private final JMenu myGameMenu;
private final JMenuItem myNewGame;
private final JMenuItem myEndGame;
private final JMenuItem myExit;
public TetrisMenu() {
myMenuBar = new JMenuBar();
myGameMenu = new JMenu("Game");
myNewGame = new JMenuItem("New Game");
myEndGame = new JMenuItem("End Game");
myExit = new JMenuItem("Exit");
createMenu();
}
private void createMenu() {
myMenuBar.add(myGameMenu);
myGameMenu.add(myNewGame);
myGameMenu.add(myEndGame);
myGameMenu.addSeparator();
myGameMenu.add(myExit);
}
public JMenuBar getMenuBar() {
return myMenuBar;
}
public JMenuItem getNewGame() {
return myNewGame;
}
public JMenuItem getEndGame() {
return myEndGame;
}
/**
*
* @return
*/
public JMenuItem getExit() {
return myExit;
}
Your JPanel's paintComponent method does not call the super's same method, and so the method breaks the painting chain and the JPanel cannot do house-keeping painting, including removal of dirty pixels. Don't do this. Call the super's method in your override.
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// .....