JPanel在JFrame上绘制时覆盖了JFrame菜单

3

我有一个JPanel对象作为JFrame组件,并使用Timer对象定期重新绘制JPanel的内容。除了JPanel在重绘时会覆盖JFrame菜单并使菜单项无法读取之外,一切都正常。是否有办法解决这个问题,而不必每次用户访问菜单时都暂停计时器?

控制框架类

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();


    }

}

动画面板类

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

问题是动画面板正在覆盖控制框架菜单。

1
解决方案是修复你代码中的错误。如果需要我们的帮助,你需要展示那段代码或者部分代码。最好提交一个SSCCE,也就是一个最少、可编译和可运行的程序,演示你的问题,并且没有任何与手头问题无关的代码。我不确定你如何想让我们在没有这个关键信息的情况下猜到错误,但也许是因为你是新来的。顺便说一下,欢迎来到Stack Overflow。 - Hovercraft Full Of Eels
发布代码是个好主意。+1 - Andrew Thompson
2个回答

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

4
你的代码存在一个问题,就是你的绘制方式是错误的。你几乎不使用组件的getGraphics方法获取其绘图对象,因为如果存在任何重绘,该对象将不会保留。相反,绘制应该被动在你JPanel的paintComponent方法中执行。
编辑:正如安德鲁在他更快的回答中展示的那样!给他点赞!
但如果你从这个练习中学到了什么,那就是你需要通过Java Swing绘图教程来学习如何在Swing中进行绘图,因为在开始进行这种编码时,你(和我们所有人)都需要放弃一些错误的假设。

感谢您提供教程建议,但更多地是因为建议“发布代码”。 :) - Andrew Thompson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接