为什么在Graphics对象上调用dispose()会导致JPanel不呈现任何组件 [英] Why does calling dispose() on Graphics object cause JPanel to not render any components

查看:123
本文介绍了为什么在Graphics对象上调用dispose()会导致JPanel不呈现任何组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在得知> dispose()应该在 Graphics / Graphics2D code>对象在使用后,我开始改变我的游戏来加入它。



当我添加 g2d.dispose()重载 paintComponent(Graphics g) JPanel ,我添加的组件(扩展名 JLabel class)在那里没有渲染我仍然可以点击它们等,但它们不会被绘制。



我用普通的 JLabel JButton 进行了测试,同样的效果(尽管 JButton 在鼠标悬停时呈现)。

所以我的问题是为什么会发生这种情况?



以下是一个SSCCE:

dispose()

在这里输入图片描述>

$ c $> paintComponent MainMenuPanel class:



  import java.awt.Color; 
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
导入javax.swing.SwingUtilities;

public class Test {

public Test(){
try {
initComponents();
} catch(Exception ex){
Logger.getLogger(Test.class.getName())。log(Level.SEVERE,null,ex);



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

private void initComponents()抛出异常{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);

MainMenuPanel mmp = new MainMenuPanel();
frame.add(mmp);

frame.pack();
frame.setVisible(true);



class MainMenuPanel扩展JPanel {

//为主菜单创建标签
private PopUpJLabel versusesModeLabel;
private PopUpJLabel singlePlayerModeLabel;
私人PopUpJLabel选项标签;
private PopUpJLabel helpLabel;
private PopUpJLabel aboutLabel;
//创建变量来保存背景
私人图像背景;
私人维度preferredDimensions;
public static String gameType;
public static final String SINGLE_PLAYER =Single Player,VERSUS_MODE =VS Mode;
$ b / **
*使用
初始化双缓冲JPanel的默认构造函数* GridBagLayout
* /
public MainMenuPanel(){
super (new GridBagLayout(),true);
尝试{
initComponents();
} catch(Exception ex){
JOptionPane.showMessageDialog(null,无法加载主菜单背景!,主菜单错误:0x004,JOptionPane.ERROR_MESSAGE);
System.exit(4);


$ b $ * b $ b *创建JPanel及其组件
* /
private void initComponents()throws Exception {

//设置JPanel的首选大小
preferredDimensions = new Dimension(800,600);

background = scaleImage(800,600,ImageIO.read(new URL(http://photos.appleinsider.com/12.08.30-Java.jpg)));

//创建标签实例
singlePlayerModeLabel = new PopUpJLabel(Single Player Mode);
singlePlayerModeLabel.setEnabled(false);

versusesModeLabel = new PopUpJLabel(Versus Mode);
optionsLabel = new PopUpJLabel(Options);
helpLabel =新建PopUpJLabel(帮助);
aboutLabel = new PopUpJLabel(About);

//为gridbag创建新的约束条件
GridBagConstraints gc = new GridBagConstraints();
gc.fill = GridBagConstraints.HORIZONTAL;
gc.ipady = 50; //垂直间距

//将newGameLabel添加到具有约束的面板
gc.gridx = 0;
gc.gridy = 0;
add(singlePlayerModeLabel,gc);

gc.gridy = 1;
add(versusesModeLabel,gc);
//将optionsLabel添加到带约束的面板(x是相同的)
gc.gridy = 2;
add(optionsLabel,gc);
//将helpLabel添加到带约束的面板(x是相同的)
gc.gridy = 3;
add(helpLabel,gc);
//将aboutLabel添加到具有约束的面板(x是相同的)
gc.gridy = 4;
add(aboutLabel,gc);
}

public static BufferedImage scaleImage(int w,int h,BufferedImage img)throws Exception {
BufferedImage bi;
// bi = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
bi = new BufferedImage(w,h,img.getType());
Graphics2D g2d =(Graphics2D)bi.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(img,0,0,w,h,null);
g2d.dispose();
返回bi;
}
$ b $ * *
*将返回JPanel的优先大小
* /
@Override
public Dimension getPreferredSize(){
返回preferredDimensions;
}
$ b $ * / $
*将使用反锯齿和质量渲染为JPanel绘制背景
* /
@Override
protected void paintComponent(Graphics grphcs){
super.paintComponent(grphcs);

//将图形对象转换为graphics2d对象
Graphics2D g2d =(Graphics2D)grphcs;

//设置抗锯齿和渲染等
//GamePanel.applyRenderHints(g2d);

//将图像作为背景
g2d.drawImage(background,0,0,null);

//g2d.dispose();//if我取消注释这个不LAbels会显示
}
}

class PopUpJLabel扩展JLabel {

public final static Font defaultFont = new Font(Arial,Font.PLAIN,50);
public final static Font hoverFont = new Font(Arial,Font.BOLD,70);

PopUpJLabel(String text){
super(text);
setHorizo​​ntalAlignment(JLabel.CENTER);
setForeground(Color.ORANGE);
setFont(defaultFont);

//允许组件为可聚焦的
setFocusable(true);

//添加焦点适配器在焦点被获取或丢失时更改fint(用于横切带有键的标签)
addFocusListener(new FocusAdapter(){
@Override
public void focusGained(FocusEvent fe){
super.focusGained(fe);
if(isEnabled()){
setFont(getHoverFont());
}


@Override
public void focusLost(FocusEvent fe){
super.focusLost(fe);
setFont(getDefaultFont());
}
});
$ b $ addMouseListener(new MouseAdapter(){
@Override
public void mouseEntered(MouseEvent me){
super.mouseEntered(me);
if( isEnabled()){
setFont(getHoverFont());
}
//调用焦点鼠标在这个组件上
requestFocusInWindow();
}
});

}

字体getDefaultFont(){
return defaultFont;
}

字体getHoverFont(){
return hoverFont;
}
}


解决方案

事情是,在 paintComponent 中使用的 Graphics 上下文是由调用者(框架)创建和提供的,它也负责处理它。



当你实际创建它时,你只需要处理 Graphics 例如调用 Component.getGraphics())。在你的情况下,你并没有创建它,你只是投它,所以在这种情况下不要调用dispose


After learning that dispose() should be called on Graphics/Graphics2D object after use, I went about changing my game to incorporate this.

When I added g2d.dispose() in overridden paintComponent(Graphics g) of JPanel, my components which I added (extensions of JLabel class) where not rendered I was able to still click on them etc but they would not be painted.

I tested with a normal JLabel and JButton with same effect (though JButton is rendered when mouse is over it).

So my question is why does this happen?

Here is an SSCCE to demonstrate:

after uncommenting call to dispose() in paintComponent of MainMenuPanel class:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Test {

    public Test() {
        try {
            initComponents();
        } catch (Exception ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

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

    private void initComponents() throws Exception {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);

        MainMenuPanel mmp = new MainMenuPanel();
        frame.add(mmp);

        frame.pack();
        frame.setVisible(true);
    }
}

class MainMenuPanel extends JPanel {

    //create labels for Main Menu
    private PopUpJLabel versusesModeLabel;
    private PopUpJLabel singlePlayerModeLabel;
    private PopUpJLabel optionsLabel;
    private PopUpJLabel helpLabel;
    private PopUpJLabel aboutLabel;
    //create variable to hold background
    private Image background;
    private Dimension preferredDimensions;
    public static String gameType;
    public static final String SINGLE_PLAYER = "Single Player", VERSUS_MODE = "VS Mode";

    /**
     * Default constructor to initialize double buffered JPanel with
     * GridBagLayout
     */
    public MainMenuPanel() {
        super(new GridBagLayout(), true);
        try {
            initComponents();
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(null, "Could not load main menu background!", "Main Menu Error: 0x004", JOptionPane.ERROR_MESSAGE);
            System.exit(4);
        }
    }

    /*
     * Create JPanel and its components
     */
    private void initComponents() throws Exception {

        //set prefered size of JPanel
        preferredDimensions = new Dimension(800, 600);

        background = scaleImage(800, 600, ImageIO.read(new URL("http://photos.appleinsider.com/12.08.30-Java.jpg")));

        //create label instances
        singlePlayerModeLabel = new PopUpJLabel("Single Player Mode");
        singlePlayerModeLabel.setEnabled(false);

        versusesModeLabel = new PopUpJLabel("Versus Mode");
        optionsLabel = new PopUpJLabel("Options");
        helpLabel = new PopUpJLabel("Help");
        aboutLabel = new PopUpJLabel("About");

        //create new constraints for gridbag
        GridBagConstraints gc = new GridBagConstraints();
        gc.fill = GridBagConstraints.HORIZONTAL;
        gc.ipady = 50;//vertical spacing 

        //add newGameLabel to panel with constraints
        gc.gridx = 0;
        gc.gridy = 0;
        add(singlePlayerModeLabel, gc);

        gc.gridy = 1;
        add(versusesModeLabel, gc);
        //add optionsLabel to panel with constraints (x is the same)
        gc.gridy = 2;
        add(optionsLabel, gc);
        //add helpLabel to panel with constraints (x is the same)
        gc.gridy = 3;
        add(helpLabel, gc);
        //add aboutLabel to panel with constraints (x is the same)
        gc.gridy = 4;
        add(aboutLabel, gc);
    }

    public static BufferedImage scaleImage(int w, int h, BufferedImage img) throws Exception {
        BufferedImage bi;
        //bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        bi = new BufferedImage(w, h, img.getType());
        Graphics2D g2d = (Graphics2D) bi.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
        g2d.drawImage(img, 0, 0, w, h, null);
        g2d.dispose();
        return bi;
    }

    /*
     * Will return the preffered size of JPanel
     */
    @Override
    public Dimension getPreferredSize() {
        return preferredDimensions;
    }

    /*
     * Will draw the background to JPanel with anti-aliasing on and quality rendering
     */
    @Override
    protected void paintComponent(Graphics grphcs) {
        super.paintComponent(grphcs);

        //convert graphics object to graphics2d object
        Graphics2D g2d = (Graphics2D) grphcs;

        //set anti-aliasing on and rendering etc
        //GamePanel.applyRenderHints(g2d);

        //draw the image as the background
        g2d.drawImage(background, 0, 0, null);

        //g2d.dispose();//if I uncomment this no LAbels will be shown
    }
}

class PopUpJLabel extends JLabel {

    public final static Font defaultFont = new Font("Arial", Font.PLAIN, 50);
    public final static Font hoverFont = new Font("Arial", Font.BOLD, 70);

    PopUpJLabel(String text) {
        super(text);
        setHorizontalAlignment(JLabel.CENTER);
        setForeground(Color.ORANGE);
        setFont(defaultFont);

        //allow component to be focusable
        setFocusable(true);

        //add focus adapter to change fints when focus is gained or lost (used for transversing labels with keys)
        addFocusListener(new FocusAdapter() {
            @Override
            public void focusGained(FocusEvent fe) {
                super.focusGained(fe);
                if (isEnabled()) {
                    setFont(getHoverFont());
                }
            }

            @Override
            public void focusLost(FocusEvent fe) {
                super.focusLost(fe);
                setFont(getDefaultFont());
            }
        });

        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent me) {
                super.mouseEntered(me);
                if (isEnabled()) {
                    setFont(getHoverFont());
                }
                //call for focus mouse is over this component
                requestFocusInWindow();
            }
        });

    }

    Font getDefaultFont() {
        return defaultFont;
    }

    Font getHoverFont() {
        return hoverFont;
    }
}

解决方案

The thing is that the Graphics context you are using in paintComponent is created and provided by the caller (the framework), which is also responsible for disposing of it.

You only need to dispose of Graphics when you actually create it yourself (for example by calling Component.getGraphics()). In your case, you're not creating it, you're just casting it, so do not call dispose in this case.

这篇关于为什么在Graphics对象上调用dispose()会导致JPanel不呈现任何组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆