为什么在Graphics对象上调用dispose()会导致JPanel不呈现任何组件

在得知在使用后应该在Graphics / Graphics2D对象上调用dispose()之后,我开始改变我的游戏以包含它。

当我在paintComponent(Graphics g)重写paintComponent(Graphics g)中添加g2d.dispose()时,我添加的组件( JLabel类的扩展)没有呈现我仍然能够点击它们等但是它们不会被绘制

我用普通的JLabelJButton测试了相同的效果(虽然当鼠标hover在它上面时会渲染JButton )。

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

这是一个SSCCE来certificate:

在此处输入图像描述

取消注释对MainMenuPanel类的paintComponentdispose()调用:

在此处输入图像描述

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

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

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

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