2012-06-17 27 views
14

का आकार बदलने तक जेपीनेल अपडेट नहीं करता है I पेंट कॉम्पोनेंट (ग्राफिक्स) को ओवरराइट करने के लिए जेपीनेल को उप-वर्गीकृत करता हूं, मैं एक jfrel में jpanel पर एक छवि खींचना चाहता हूं।जेपीएनएल

लेकिन मेरी छवि तब तक दिखाई नहीं दे रही है जब तक कि मैं jframe के आकार में बदलाव नहीं करता।

public class ImagePanel extends JPanel{ 

    public void setImage(BufferedImage bi) 
    { 
     image = bi; 
     revalidate(); 
    } 

    @Override 
    public void paintComponent(Graphics g) 
    { 
     super.paintComponent(g); 
     if(image != null) 
     { 
      g.drawImage(image, 0, 0, this); 
     } 
    } 
} 

उत्तर

7

आप "रीफ्रेश करें" चाहते हैं JPanel तो आप रीपेंट(), फोन करना चाहिए जो आपके paintComponent (कॉल करेंगे): यह मेरा कोड है।

public void setImage(BufferedImage bi) 
{ 
    image = bi; 
    EventQueue.invokeLater(new Runnable() 
    { 
     public void run() 
     { 
      repaint(); 
     } 
    }); 
} 

इसका अच्छा अद्यतन करें और EDT का उपयोग कर जीयूआई को बदलने के लिए अभ्यास: यह आपकी समस्या का समाधान करना चाहिए। EDT पर यहाँ और अधिक जानकारी यदि आप रुचि रखते हैं:

How does the event dispatch thread work?

repaint EDT से कहा जाने की जरूरत नहीं है। यदि आप जीयूआई बदल रहे हैं, जैसे कि जेएलएबल में टेक्स्ट सेट करना, यह ईडीटी के अंदर होना चाहिए। क्या EDT (अच्छा गाय के सौजन्य से) के बाहर कहा जा सकता है पर यहाँ और अधिक जानकारी:

Safe to use Component.repaint() outside EDT?

+0

जॉन धन्यवाद, यह पूरी तरह से काम करता है! मूल्यवान इनपुट के लिए – nautilusvn

+1

+1। बस एक सुझाव, ईडीटी के अंदर 'repaint()' कॉल डालने की कोई ज़रूरत नहीं है, क्योंकि किसी भी धागे से 'repaint() 'को कॉल करना सुरक्षित है, जैसा कि यहां बताया गया है [http://stackoverflow.com/questions/9786497/safe उपयोग करने के लिए-घटक-repaint-out-edt/9786598 # 97865 9 8) –

+1

"स्विंग घटकों के उप-वर्ग जिनके पास यूआई प्रतिनिधि है ... को 'super.paintComponent()' "- [* पेंट विधि *] (http: //java.sun.com/products/jfc/tsc/articles/painting/index.html#callback)। – trashgod

18

सत्यापित करें कि आप setVisible() के बाद जोड़ने घटकों और pack() बुला आह्वान, के रूप में यह संबंधित example में चर्चा की। आपको उचित layout को अपनाने की भी आवश्यकता हो सकती है। repaint() को आमंत्रित करते हुए, जैसा कि here सुझाया गया है, लक्षण को ठीक कर सकता है लेकिन अंतर्निहित कारण नहीं।

2

मुझे एक ही समस्या थी और कॉल सेट द्वारा इसे ठीक किया गया (सत्य); मैं जिस जेफ्रेम का उपयोग कर रहा था।

उदाहरण: साथ

jframe.setContentPane(new MyContentPane()); 

ठीक यह: अगर आपके JFrame उपयोग करने के बाद अपडेट नहीं करता

jframe.setContentPane(new MyContentPane()); 
jframe.setVisible(true); 

मुझे पता है कि यह यह करने के लिए भले ही अपने JFrame पहले से ही दिख रहा है मूर्खतापूर्ण लगता है, लेकिन यह एकमात्र तरीका है जिसे मैंने इस समस्या को ठीक करने के लिए अभी तक पाया है (ऊपर प्रस्तावित समाधान मेरे लिए काम नहीं करता है)।

यहां एक पूरा उदाहरण है। इसे चलाएं और फिर "f.setVisible (true) को असम्बद्ध करें;" कक्षा पैनल 1 और पैनल 2 में निर्देश और आप अंतर देखेंगे। आयात को न भूलें (स्वचालित आयात के लिए Ctrl + Shift + O)।

मुख्य वर्ग:

public class Main { 
    private static JFrame f; 
    public static void main(String[] args) { 
     f = new JFrame(); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.setContentPane(new Panel1(f)); 
     f.pack();  
     f.setVisible(true); 
    } 
} 

Panel1 वर्ग:

public class Panel1 extends JPanel{ 
    private JFrame f; 
    public Panel1(JFrame frame) { 
     f = frame; 
     this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); 
     JButton b = new JButton("Panel 1"); 
     b.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       f.setContentPane(new Panel2(f)); 
       // Uncomment the instruction below to fix GUI "update-on-resize-only" problem 
       //f.setVisible(true); 
      } 
     }); 
     add(b); 
    } 
} 

Panel2 वर्ग:

public class Panel2 extends JPanel{ 
    private JFrame f; 
    public Panel2(JFrame frame) { 
     f = frame; 
     this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); 
     JButton b = new JButton("Panel 2"); 
     b.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       f.setContentPane(new Panel1(f)); 
       // Uncomment the instruction below to fix GUI "update-on-resize-only" problem 
       //f.setVisible(true); 
      } 
     }); 
     add(b); 
    } 
} 

आशा है कि मदद करता है।

सम्मान।

+0

बिल्कुल सही! यकीन नहीं है कि यह क्यों काम करता है, लेकिन यह एकमात्र चीज है जिसने मेरी समस्या हल की है। इससे पहले, मैं यह कर रहा था: आयाम आकार = frame.getSize(); \t बूलियन अधिकतम = frame.getExtendedState() == JFrame.MAXIMIZED_BOTH; \t frame.setSize (नया आयाम ((int) size.getWidth() - 1, (int) size.getHeight() - 1)); \t अगर (maximized) frame.setExtendedState (JFrame.MAXIMIZED_BOTH); \t अन्य फ्रेम.सेट आकार (आकार); आपका जवाब बहुत अधिक है, बहुत साफ और रास्ता कम हैकी। धन्यवाद! – dberm22

+1

@ dberm22 वास्तव में, हैकिंग के लिए वास्तव में कोई आवश्यकता नहीं है (कम से कम इस उदाहरण में नहीं, मूल रूप से विभिन्न आकारों की छवि के साथ मूल की जांच नहीं की, न ही विस्तारित आकार के राज्य जो भी मुश्किल हो सकते हैं): सामग्री सेट करना एक है फ्रेम के कंटेनर पदानुक्रम में संशोधन और इस तरह फ्रेम पर एक पुनर्मूल्यांकन की आवश्यकता है। – kleopatra

5

JPanel.add() के लिए the docs पर एक नज़र डालें, जो यह java.awt.Container से विरासत:

इस कंटेनर के अंत करने के लिए निर्दिष्ट घटक जोड़ता है। यह addImpl (java.awt.Component, java.lang.Object, int) के लिए एक सुविधाजनक तरीका है। यह विधि लेआउट से संबंधित जानकारी को बदलती है, और इसलिए, घटक पदानुक्रम को अमान्य करता है। यदि कंटेनर पहले ही प्रदर्शित हो चुका है, तो जोड़ा गया घटक प्रदर्शित करने के लिए पदानुक्रम को उसके बाद सत्यापित किया जाना चाहिए।

जोर जोड़ा गया।

इसलिए, यदि आप के बाद एक कंटेनर संशोधित यह पहले से ही है, ताकि यह दिखाने के लिए प्रदर्शित किया गया है आप चाहिए कॉल validate()। बस repaint() का आह्वान पर्याप्त नहीं है। आपने देखा होगा कि setVisible(true) पर कॉल करना भी काम करता है; ऐसा इसलिए है क्योंकि it calls validate() internally