2010-03-12 15 views
29

मुझे एक उदाहरण मिला जिसमें पैनलों में बटन जोड़े गए हैं (JPanel के उदाहरण) तो पैनलों को कंटेनरों में जोड़ा जाता है (getContentPane() द्वारा उत्पन्न उदाहरण) और फिर कंटेनर, निर्माण द्वारा, JFrame (विंडोज़) में शामिल हैं।कंटेंटपेन और जेपीनेल के बीच संबंध क्या है?

  1. मैं कंटेनर से छुटकारा मिला:

    मैं दो बातें करने की कोशिश की। अधिक जानकारी में, मैंने पैनल में बटन जोड़े (JPanel का उदाहरण) और फिर मैंने विंडोज़ में पैनल जोड़ा (JFrame का उदाहरण)। यह ठीक काम किया।

  2. मैंने पैनलों से छुटकारा पा लिया। अधिक जानकारी में, मैंने सीधे कंटेनर पर बटन जोड़े और फिर मैंने विंडो में कंटेनर जोड़ा (JFrame का उदाहरण)।

तो, मुझे दो चीजें समझ में नहीं आती हैं।

  1. हमारे पास एक ही चीज करने के लिए दो प्रतिस्पर्धी तंत्र क्यों हैं?

  2. पैनलों के साथ संयोजन में कंटेनर का उपयोग करने का क्या कारण है (JPanel)? (उदाहरण के लिए, हम जेपीनल में बटन शामिल करने के लिए क्या करते हैं और फिर हम कंटेनरों में जेपीनल शामिल करते हैं)। क्या हम JPanelJPanel में शामिल कर सकते हैं? क्या हम कंटेनर में एक कंटेनर शामिल कर सकते हैं?

जोड़ा:

frame.getContentPane().add(panel); 

क्या के लिए हम में getContentPane() डाल के बीच:

हो सकता है कि मेरे सवाल का सार कोड में से एक लाइन में रखा जा सकता है? मैंने बस frame.add(panel); की कोशिश की और यह ठीक काम करता है।

जोड़ा 2:

मैं चाहते हैं कि मैं क्या मतलब के बारे में अधिक स्पष्ट होना कुछ कोड जोड़ने के लिए। इस उदाहरण में मैं केवल JPane का उपयोग करें:

import java.awt.*; 
import javax.swing.*; 
public class HelloWorldSwing { 
    public static void main(String[] args) { 
     JFrame frame = new JFrame("HelloWorldSwing"); 
     JPanel panel = new JPanel(); 
     panel.setLayout(new BorderLayout());   
     panel.add(new JButton("W"), BorderLayout.NORTH); 
     panel.add(new JButton("E"), BorderLayout.SOUTH); 
     frame.add(panel); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setVisible(true); 
    } 
} 

और इस उदाहरण में मैं केवल सामग्री फलक का उपयोग करें:

import java.awt.*; 
import javax.swing.*; 
public class HelloWorldSwing { 
    public static void main(String[] args) { 
    JFrame frame = new JFrame("HelloWorldSwing"); 
    Container pane = frame.getContentPane(); 
    pane.setLayout(new BorderLayout()); 
    pane.add(new JButton("W"), BorderLayout.NORTH); 
    pane.add(new JButton("E"), BorderLayout.SOUTH); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.pack(); 
    frame.setVisible(true); 
    } 
} 

दोनों काम ठीक! मैं सिर्फ यह जानना चाहता हूं कि चीजों को करने के इन दो तरीकों के बीच एक बेहतर (सुरक्षित) है।

उत्तर

27

यह न दो प्रतिस्पर्धी तंत्र है - एक JPanelएकContainer (बस JPanel javadocs के शीर्ष पर वर्ग पदानुक्रम को देखो) है। JFrame.getContentPane() को JFrame में प्रदर्शित करना चाहते हैं, तो बस Container लौटाएं। आंतरिक रूप से, यह JPanel का उपयोग कर रहा है (डिफ़ॉल्ट रूप से - आप इसे setContentPane() पर कॉल करके बदल सकते हैं) क्योंकि यह को JPanel के बजाय क्यों लौटा रहा है - ऐसा इसलिए है क्योंकि आपको program to an interface, not an implementation - उस स्तर पर, आपको इसकी देखभाल करने की आवश्यकता है कि आप Component एस को कुछ जोड़ सकते हैं - और भले ही Container इंटरफ़ेस की बजाय एक कक्षा है - यह वास्तव में ऐसा करने के लिए आवश्यक इंटरफ़ेस प्रदान करता है।

के लिए क्यों दोनों JFrame.add() और JFrame.getContentPane().add() दोनों एक ही बात करते हैं - JFrame.add()JFrame.getContentPane().add() कॉल करने के लिए ओवरराइड है। यह हमेशा मामला नहीं था - प्री-जेडीके 1.5 आपको हमेशा JFrame.getContentPane().add() निर्दिष्ट करना था और JFrame.add() ने RuntimeException फेंक दिया, अगर आपने इसे बुलाया, लेकिन कई शिकायतों के कारण, यह जेडीके 1.5 में बदल गया था जो आप चाहते थे।

+0

@Nate देखें, "आंतरिक रूप से, यह एक जेपीनल का उपयोग कर रहा है" का क्या मतलब है। आपका मतलब है कि कंटेनर एक जेपीनेल का उपयोग कर रहा है? उससे तुम्हारा क्या मतलब है? हालांकि मैं जेपीनेल कंटेनर का उप-वर्ग है। और मैं "setContentPane" से क्या बदल सकता हूं? ठीक। आप कहते हैं कि कंटेनर एक वर्ग है (और मैं हमेशा कंटेनर को कक्षा के रूप में मानता हूं)। लेकिन जेपेन भी एक वर्ग है। हम सिर्फ जेपीन या सिर्फ कंटेनर का उपयोग क्यों नहीं कर सकते?मैं केवल जेपीन का उपयोग करके वही काम करने में सक्षम था। मैं केवल कंटेनरों का उपयोग कर ऐसा करने में भी सक्षम था। – Roman

+0

'जेएफआरएएम' 'getContentPane()' विधि को वापस करने के लिए आंतरिक रूप से 'जेपीनल' ऑब्जेक्ट का उपयोग कर रहा है। यही कारण है कि जॅचरी का जवाब काम करता है। वास्तविक 'जेपीनेल' संदर्भ को 'JFrame.rootPane' फ़ील्ड में दफनाया गया है। आप 'जेएफआरएएम' पर 'setContentPane()' को कॉल करेंगे - उदाहरण के लिए, आप 'frame.add (पैनल) 'से' frame.setContentPane (पैनल)' से अपने पहले उदाहरण में लाइन 10 बदल सकते हैं। 'कंटेनर 'एक वर्ग है। 'जेपीनेल' एक वर्ग है (जो 'कंटेनर' का उप-वर्ग है)। आप रेफरेंस संदर्भों के ऑब्जेक्ट के प्रकार के साथ संदर्भ के प्रकार को भ्रमित कर रहे हैं। 'कंटेनर कंटेनर = नया जेपीनेल()' – Nate

+0

@ स्रोत के बारे में सोचें (http://pragmaticjava.blogspot.com.ar/2008/08/program-to-interface-not-implementation.html) को हटा दिया गया है। – Lucio

1

मेरा मानना ​​है कि इसका कारण यह है कि स्विंग एडब्ल्यूटी से बनाया गया था, और कंटेनर एक शीर्ष स्तर एडब्ल्यूटी ऑब्जेक्ट है। यह वास्तव में सबसे बड़ी डिजाइन पसंद नहीं है, हालांकि, आप आम तौर पर स्विंग (हल्के वजन) के साथ एडब्ल्यूटी (हेवीवेट) वस्तुओं को मिश्रण नहीं करना चाहते हैं।

मुझे लगता है कि इसे संभालने का सबसे अच्छा तरीका हमेशा सामग्री जेननेल में डालना है।

JPanel contentPanel = (JPanel)aFrame.getContentPane(); 
+0

यह एडब्ल्यूटी और स्विंग घटकों को मिश्रण नहीं कर रहा है ... मेरा उत्तर – Nate

1

यह सब पिछले संस्करण API doc कि JFrame.add() (nowerdays) के लिए पर्याप्त है में लिखा है।

आप पुराने जावा संस्करणों here से तुलना कर सकते हैं।

3

अच्छा सवाल। मुझे यह समझने में मदद मिली कि "स्विंग तीन आम तौर पर उपयोगी शीर्ष-स्तरीय कंटेनर कक्षाएं प्रदान करता है: JFrame, JDialog, और JApplet ... ... सुविधा के रूप में, ऐड विधि और इसके रूप, निकालें और सेटआउट को आगे बढ़ाने के लिए ओवरराइड किया गया है सामग्री के रूप में आवश्यक है। "- Using Top-Level Containers

1

दिलचस्प: jframe.setBackground(color) मेरे लिए काम नहीं करता है, लेकिन jframe.getContentPane().setBackground(color) काम करता है।

1

इस के इतिहास और मैकेनिक्स पर कुछ विवरणों में this leepoint article पर भी चर्चा की गई है। विशेष रूप से ध्यान दें:

getContentPane()Container ऑब्जेक्ट देता है। यह वास्तव में एक सादा Container ऑब्जेक्ट नहीं है, लेकिन वास्तव में JPanel है! पदानुक्रम के परिणामस्वरूप यह Container है। इसलिए यदि हमें पूर्वनिर्धारित सामग्री फलक मिलती है, तो यह वास्तव में JPanel है, लेकिन हम वास्तव में JComponent द्वारा जोड़े गए कार्यक्षमता का लाभ नहीं उठा सकते हैं।

और

वे JFrame में add() तरीकों जो केवल सामग्री फलक के लिए इसी add() तरीकों फोन को परिभाषित किया। अब इस सुविधा को जोड़ने के लिए अजीब लगता है, खासकर जब से कई लेआउट एकाधिक नेस्टेड पैनलों का उपयोग करते हैं, इसलिए आपको अभी भी JPanel पर सीधे जोड़ने के साथ सहज रहना होगा। और सामग्री फलक के साथ जो भी आप करना चाहते हैं वह JFrame पर कॉल के माध्यम से नहीं किया जा सकता है।

संबंधित मुद्दे