Warum funktioniert der Aufruf von dispose() auf dem Graphics-Objekt, Ursache JPanel nicht im Stande alle Komponenten
Nach dem lernen, dass dispose()
aufgerufen werden soll Graphics
/Graphics2D
Objekt nach Nutzung, ging ich über die änderung meiner Spiel zu übernehmen.
Wenn ich Hinzugefügt g2d.dispose()
im überschrieben paintComponent(Graphics g)
von JPanel
meine Komponenten, die ich Hinzugefügt (Erweiterungen von JLabel
Klasse), wo nicht gerendert war, konnte ich immer noch auf Sie, etc., aber Sie würde nicht lackiert.
Getestet habe ich mit einem normalen JLabel
und JButton
mit dem gleichen Effekt (obwohl JButton
dargestellt wird, wenn die Maus über es).
Also meine Frage ist, warum geschieht dies?
Hier ist ein SSCCE zu demonstrieren:
nachdem Sie die Kommentarzeichen Aufruf dispose()
im paintComponent
von MainMenuPanel
Klasse:
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;
}
}
- "Nach dem lernen, dass dispose() sollte aufgerufen werden, auf Graphics/Graphics2D-Objekt nach der Verwendung" Wo haben Sie das erfahren?
- interessiert das "wo" als auch ...
- Es war ein Kommentar auf eine Antwort von mir, es hatte zu tun mit der Skalierung ein Bild über Grafiken, so dass es richtig war, aber ich nahm es, wir müssen es tun, wenn arbeiten mit Grafiken-Objekte
- vielen Dank für die Klarstellung - Lektion gelernt: glaube nicht jeden Kommentar 🙂
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Sache ist, dass die
Graphics
Kontext Verwendung inpaintComponent
erstellt und zur Verfügung gestellt durch den Anrufer (der Rahmen), die auch zuständig ist für die Entsorgung von it.Müssen Sie nur entsorgen
Graphics
wenn Sie tatsächlich Sie selbst erstellen (zum Beispiel durch aufrufenComponent.getGraphics()
). In Ihrem Fall sind Sie nicht erstellen, Sie sind nur casting, so rufen Sie nicht entsorgen in diesem Fall.Component.getGraphics()
erstellen Sie eine neueGraphics
? Mein Verständnis war, dassGraphics.createGraphics()
hat, aber nicht eine einfachegetGraphics()
. Und sowieso, ich glaube, dass der AufrufgetGraphics()
ist in der Regel eine schlechte Idee und sollte vermieden werden.getGraphics
sollte vermieden werden, aber es ist ausdrücklich in der Dokumentation als eine Möglichkeit, erhalten Sie einenGraphics
Kontext. AuchgetGraphics
Dokumentation sagen: Erstellt ein Grafik-Kontext..., also gehe ich davon aus, dass eine neue erstellt jedes mal. NatürlichBufferedImage.createGraphics
ist auch ein Weg, um eineGraphics
Kontext.Weil
.dispose()
Versionen Ihrer Ressourcen. Ja, alles.