在 JFrame 和 JPanel 中显示的 JMenuBar

JMenuBar showing in both the JFrame and JPanel

我遇到了一件奇怪的事情,JMenuBar 同时出现在我的 JFrame 和 JPanel 中。我不知道这是怎么回事。我不太确定是因为菜单栏和 JPanel 不同 类 还是来自观察者模式。

What it looks like when I run it.

JFrame代码

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

}

J面板代码

 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;
}

菜单条码

 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;
 }

您的 JPanel 的 paintComponent 方法没有调用 super 的相同方法,因此该方法中断了绘画链,JPanel 无法进行 house-keeping 绘画,包括去除脏像素。不要这样做。在您的覆盖中调用 super 的方法。

@Override
protected void paintComponent(Graphics g)  {
    super.paintComponent(g);
    // .....