gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:28:47 25 4
gpt4 key购买 nike

在得知 dispose() 应该在 Graphics/Graphics2D 对象上调用后,我着手改变我的游戏以合并它.

当我在 JPanel 的覆盖 paintComponent(Graphics g) 中添加 g2d.dispose() 时,我添加的组件(扩展JLabel 类)在没有呈现的地方我仍然可以点击它们等但它们不会被绘制

我用普通的 JLabelJButton 进行了测试,效果相同(虽然 JButton 在鼠标悬停时呈现)。

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

这是一个 SSCCE 来演示:

enter image description here

MainMenuPanel 类的 paintComponent 中取消对 dispose() 的调用后:

enter image description here

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 时处理它(例如通过调用Component.getGraphics())。在您的情况下,您不是在创建它,而是在转换它,所以在这种情况下不要调用 dispose

关于java - 为什么在 Graphics 对象上调用 dispose() 会导致 JPanel 不呈现任何组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13911743/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com