2012-12-17 42 views
6

प्रदान नहीं करने के लिए, मैं अपने खेल को बदलने के लिए इस को शामिल करने के बारे में चला गया।क्यों बुला करता निपटान() ग्राफिक्स वस्तु कारण JPanel आपको तैयार कर रही है कि <code>dispose()</code> पर उपयोग के बाद <code>Graphics</code>/<code>Graphics2D</code> वस्तु बुलाया जाना चाहिए के बाद किसी भी घटक

जब मैं JPanel की ओवरराइड paintComponent(Graphics g) में g2d.dispose() कहा, मेरी घटकों जो मैं जोड़ा (JLabel वर्ग के एक्सटेंशन) जहां गाया नहीं मैं अब भी उन्हें आदि पर क्लिक करने में सक्षम था, लेकिन वे चित्रित नहीं होगा।

मैंने एक सामान्य प्रभाव के साथ सामान्य JLabel और JButton के साथ परीक्षण किया (हालांकि JButton माउस पर होने पर प्रस्तुत किया जाता है)।

तो मेरा सवाल यह है कि ऐसा क्यों होता है?

enter image description here

MainMenuPanel वर्ग के paintComponent में dispose() को uncommenting कॉल के बाद:

यहाँ दर्शाने के लिए एक SSCCE है

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

"सीखने के बाद ग्राफिक्स/ग्राफिक्स 2 डी ऑब्जेक्ट पर इसका निपटान() को कॉल करने के बाद कहा जाना चाहिए" आप इसे कहां से सीख चुके थे? – msell

+0

"जहां" में रुचि रखते हैं ... – kleopatra

+0

@ क्लेओपेट्रा यह मेरे उत्तर पर एक टिप्पणी थी, इसे ग्राफिक्स के माध्यम से एक छवि स्केल करने के साथ करना था, इसलिए यह सही था हालांकि मैंने इसे लिया था जब भी हम साथ काम करते हैं ग्राफिक्स ऑब्जेक्ट्स –

उत्तर

20

बात यह है कि Graphics संदर्भ आपमें उपयोग कर रहे हैंकॉलर (ढांचा) द्वारा बनाया और प्रदान किया गया है, जो इसे निपटाने के लिए भी जिम्मेदार है।

आपको वास्तव में Graphics का निपटान करने की आवश्यकता है जब आप वास्तव में इसे स्वयं बनाते हैं (उदाहरण के लिए Component.getGraphics() पर कॉल करके)। आपके मामले में, आप इसे नहीं बना रहे हैं, आप बस इसे कास्ट कर रहे हैं, इसलिए इस मामले में का निपटान न करें।

+0

+1 धन्यवाद, मैं आपकी गलती देखता हूं, हालांकि हर बार जब हम ऑब्जेक्ट का उपयोग करते हैं तो इसे पेंट कॉम्पोनेंट इत्यादि में इस्तेमाल किया जाना चाहिए। –

+2

मुझे समझ में नहीं आ रहा है कि आप क्यों कहते हैं _ आपको केवल ग्राफिक्स का निपटान करने की आवश्यकता है जब आप वास्तव में इसे स्वयं बनाते हैं (उदाहरण के लिए Component.getGraphics() को कॉल करके) ._ जब आप 'Component.getGraphics()' को कॉल करते हैं, तो क्या आप एक बनाते हैं नया 'ग्राफिक्स'? मेरी समझ यह थी कि 'Graphics.createGraphics() 'करता है, लेकिन एक सरल' getGraphics()' नहीं है। और वैसे भी, मेरा मानना ​​है कि 'getGraphics()' को कॉल करना आमतौर पर एक बुरा विचार है और इससे बचा जाना चाहिए। –

+0

आप सही हैं कि 'गेटग्राफिक्स' से बचा जाना चाहिए, लेकिन इसे 'ग्राफिक्स' संदर्भ प्राप्त करने के तरीके के रूप में दस्तावेज़ों में स्पष्ट रूप से बताया गया है। साथ ही, 'गेटग्राफिक्स' दस्तावेज कहता है: * एक ग्राफिक्स संदर्भ बनाता है ... *, इसलिए मुझे लगता है कि हर बार एक नया बनाया जाता है। बेशक, 'BufferedImage.createGraphics' भी 'ग्राफिक्स' संदर्भ बनाने का एक तरीका है। उत्तर के लिए –

3

क्योंकि .dispose() आपके संसाधनों को रिलीज़ करता है। हाँ सबकुछ।

+0

+1 धन्यवाद –