JFrame中的JPanel绘制在JFrame菜单的顶部

时间:2012-02-04 04:27:24

标签: java swing graphics jframe jpanel

所以我有一个JPanel对象作为JFrame的一个组件,我定期用Timer对象重绘JPanel的内容。一切正常,除了在JFrame菜单顶部重绘JPanel,因此菜单项不可读。有没有办法解决这个问题,而不必在每次用户访问菜单时暂停计时器?

控制框架类

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ControlFrame extends JFrame implements ActionListener{
    /*======Public Constants======*/
    public static int DEFAULT_HEIGHT = 400;
    public static int DEFAULT_WIDTH = 400;

    /*======Private Instance Variables======*/
    private AnimationPanel animPane;
    private JMenu menu;
    private JMenuItem menuExit;
    private JMenuBar menuBar;

    /*======Constructors======*/
    public ControlFrame(){
        initialize();
    }

    /*======Public Instance Methods======*/
    public void actionPerformed(ActionEvent ae) {
        if(ae.getActionCommand().equals("exit")){
                System.exit(0);
        }
    }

    /*======Private Instance Methods======*/
    private void initialize(){
        this.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        this.setLayout(new GridLayout(0,2));

        this.animPane = new AnimationPanel(this.getWidth(), this.getHeight());

        this.add(animPane);

        createCFMenu();

        this.setVisible(true);
    }

    private void createCFMenu(){
        this.menuBar = new JMenuBar();
        this.menu = new JMenu("File");
        this.menu.setMnemonic(KeyEvent.VK_F);
        this.menuBar.add(this.menu);

        this.menuExit = new JMenuItem("Exit", KeyEvent.VK_X);
        this.menuExit.addActionListener(this);
        this.menuExit.setActionCommand("exit");
        this.menu.add(menuExit);

        this.setJMenuBar(this.menuBar);
    }

    /*======Main Method======*/
    public static void main(String[] args){
        ControlFrame cf = new ControlFrame();


    }

}

AnimationPanel类

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;

public class AnimationPanel extends JPanel implements ActionListener{



    /*======Private Instance Variables======*/
    private int timeInterval;
    private Timer animTimer;

    /*======Constructor======*/
    public AnimationPanel(int width, int height){
        timeInterval = 50;

        this.setSize(width, height);

        this.animTimer = new Timer(timeInterval, this);

        animTimer.start();
    }


    public void actionPerformed(ActionEvent arg0) {

        paint();
    }

    /*======Private Instance Variables======*/
    private void paint(){
        BufferedImage bImage = new BufferedImage(this.getWidth(), 
            this.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics bg = bImage.getGraphics();

        bg.setColor(Color.WHITE);
        bg.fillRect(0, 0, bImage.getWidth(), bImage.getHeight());

        this.getGraphics().drawImage(bImage, 0, 0, this);
    }
} 

问题是动画面板正在绘制ControlFrames菜单的顶部

2 个答案:

答案 0 :(得分:4)

不要在Java代码中调用getGraphics()。 Java GUI必须在被告知这样做时重新绘制,并且应该使用paint(Graphics)paintComponent(Graphics)进行重新绘制。这就是菜单消失的原因。

此版本的AnimationPanel已解决该错误。

class AnimationPanel extends JPanel implements ActionListener{
    /*======Private Instance Variables======*/
    private int timeInterval;
    private Timer animTimer;

    /*======Constructor======*/
    public AnimationPanel(int width, int height){
        timeInterval = 50;
        this.setSize(width, height);
        this.animTimer = new Timer(timeInterval, this);
        animTimer.start();
    }

    public void actionPerformed(ActionEvent arg0) {
        repaint();
    }

    /*======Private Instance Variables======*/
    public void paintComponent(Graphics g){
        // important to get the component to paint itself & borders etc.
        super.paintComponent(g); 
        BufferedImage bImage = new BufferedImage(this.getWidth(),
            this.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics bg = bImage.getGraphics();

        bg.setColor(Color.WHITE);
        bg.fillRect(0, 0, bImage.getWidth(), bImage.getHeight());
        bg.dispose();  // Assist the garbage collector!

        g.drawImage(bImage, 0, 0, this);
    }
}

答案 1 :(得分:4)

您的代码存在的一个问题是您的错误。你几乎从不使用组件的getGraphics来获取它的Graphics对象,因为如果有任何重绘,这个对象将不会持久存在。相反,应该在JPanel的paintComponent方法中被动地执行绘制。

编辑:正如安德鲁在他更快的帖子中所展示的那样! 1+给他!

但是如果你从这个练习中得到任何东西,那就是你需要通过Java Swing图形教程来学习如何在Swing中绘制,因为你需要抛弃一些错误的假设(你和我们所有人) )在开始做这种编码时有。