在了解到graphics
/graphics2d
对象在使用后应该调用dispose()
之后,我开始修改我的游戏以合并这一点。
当我在JPanel
的重写的PaintComponent(Graphics g)
中添加G2d.Dispose()
时,我添加的组件(JLabel
类的扩展)在没有呈现的地方仍然能够单击它们,但它们不会被绘制。
我使用普通的JLabel
和具有相同效果的JButton
进行了测试(不过鼠标在JButton
上时会呈现)。
所以我的问题是为什么会发生这种情况?
下面是一个SSCCE演示:
取消对MainMenupAnel
类的PaintComponent
中的Dispose()
调用的注释后:
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
上下文是由调用方(框架)创建和提供的,它也负责处理它。
您只需要在自己实际创建图形
时处理它(例如,通过调用component.getGraphics()
)。在您的示例中,您不是在创建它,而是在转换它,因此在这种情况下不要调用dispose。
这个问题在这里总结得很好;基本上,如果您在useEffect中有一个异步函数(这是您期望的函数),您将导致每个更新状态的组件的重新呈现。我通常不想像作者的解决方案/变通方法那样把事情堆在一起,对我来说,这种行为没有意义(您希望所有的状态更新都一起发生)。
我试着读过类似的问题,但没有成功。
问题内容: 我这里有一些简单的代码 每次单击按钮,控制台上都会显示2条日志,指示该组件呈现两次。 这是一个codeandbox链接,可以尝试一下。 问题答案: 呈现您的App组件的原因是在其中导致代码在严格模式下运行,并且在严格模式下,控制台显示两次,因为每个功能在开发模式下均运行两次 根据react docs: 严格模式无法自动为您检测副作用,但可以通过使其更具确定性来帮助您发现它们。这是通过有
情况:JDesktopPane中有供应商_JinternalFrame。JDesktopPane中的call SetVisible(true)有一个Supplier_按钮,用于显示供应商框架。但当我通过Dispose()关闭供应商框架时;再次单击按钮后,它将隐藏并不再显示。有两个选项可以使用setshow();和setHide()而不是setDispose()。但我想重新创建Jinternalfr
问题内容: 请查看此非常简单的代码段,以在下面说明我的问题: 该标签 之后 的元素,在HTML代码。 由于我不更改其属性,因此必须为。而且,据我所知,元素是根据页面的流向定位的。 那么……为什么绝对位置 显示在 其同级 上方? 我希望它会在第一时间出现。 请注意,我知道如何 纠正 此行为,我只是在问为什么! 修正片段: ......为什么使用上更正此行为? 问题答案: 这就是绘画顺序的工作方式。如
我目前正在学习Spring Boot和GraphQL。对于graphql,我正在使用graphql spqr库,遇到了一个graphql错误。我可以使用localhost:8080/gui对我的graphql api进行查询和修改,但当我使用Postman或从前端调用时,我会收到下面的错误消息。在gui中,endpoint似乎仍然是/graphql,但当我将同一个endpoint与Postman或