9

在了解dispose()应该在使用后调用Graphics/Graphics2D对象之后,我开始改变我的游戏以合并它。

当我添加g2d.dispose()覆盖paintComponent(Graphics g)JPanel,我添加的组件(类的扩展JLabel)未渲染时,我仍然能够单击它们等,但它们不会被绘制

我用正常JLabelJButton相同的效果进行了测试(尽管JButton在鼠标悬停时呈现)。

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

这是一个 SSCCE 来演示:

在此处输入图像描述

dispose()在取消注释对课堂的调用paintComponentMainMenuPanel

在此处输入图像描述

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

2 回答 2

24

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

您只需要Graphics在您自己实际创建它时进行处理(例如通过调用Component.getGraphics())。在你的情况下,你不是在创建它,你只是在投射它,所以在这种情况下不要调用 dispose 。

于 2012-12-17T09:52:25.447 回答
2

因为.dispose()释放你的资源。是的,一切。

于 2012-12-17T09:52:38.157 回答