2015-11-30 5 views
6

लघु संस्करणक्यूटी में आइटम दृश्यों के लिए डिफ़ॉल्ट प्रतिनिधि के यांत्रिकी क्या हैं?

क्या QTreeView द्वारा इस्तेमाल किया डिफ़ॉल्ट प्रतिनिधि है? विशेष रूप से मैं अपनी paint() विधि खोजने की कोशिश कर रहा हूं?

अधिक बड़ा संस्करण

मैं एक अजगर उपयोगकर्ता (Pyside/PyQt) हूँ, और QTreeView की कार्यक्षमता के कुछ पुन: बनाने के लिए एक कस्टम प्रतिनिधि उपयोग कर रहा हूँ। इसलिए, मैं डिफ़ॉल्ट प्रतिनिधि और पेंट विधि खोजने की कोशिश कर रहा हूं, जिसका प्रयोग QTreeView में किया जाता है। इससे भी बेहतर होगा कि यह कैसे काम करता है इसका एक स्पष्टीकरण होगा।

क्रॉस पोस्ट

मैं क्यूटी केंद्र (http://www.qtcentre.org/threads/64458-Finding-default-delegate-for-QTreeView?) में एक ही प्रश्न पोस्ट किया।

उत्तर

8

tl; डॉ

सभी आइटम विचारों के लिए डिफ़ॉल्ट प्रतिनिधि QStyledItemDelegate है। इसकी paint() विधि प्रत्येक आइटम को आकर्षित करने के लिए qcommonstyle.cpp में परिभाषित drawControl() को आमंत्रित करती है। इसलिए, प्रत्येक आइटम को कैसे खींचा जाता है, इस बारे में जानकारी के लिए qcommonstyle.cpp पर ध्यान दें।


लंबे समय फार्म जवाब

जो लोग पसंद करते हैं संक्षिप्तता tl पढ़ना चाहिए, ऊपर और documentation on Styles in Item Views डॉ। यदि आप अभी भी अटक गए हैं (और शायद कई पायथन उपयोगकर्ता होंगे), तो बाकी के उत्तर में मदद करनी चाहिए।

मैं डिफ़ॉल्ट प्रतिनिधि QStyledItemDelegate विचारों में आइटम के लिए डिफ़ॉल्ट प्रतिनिधि है QStyledItemDelegate

है। यह Qt's Model/View Programming overview में स्पष्ट रूप से कहा गया है:

क्यूटी 4.4 के बाद से, डिफ़ॉल्ट प्रतिनिधि कार्यान्वयन QStyledItemDelegate द्वारा प्रदान की जाती है, और इस क्यूटी के मानक देखा गया डिफ़ॉल्ट प्रतिनिधि के रूप में प्रयोग किया जाता है।

जब क्यूटी आइटम दृश्य, जैसे, एक QTableView में मॉडल से डेटा प्रदर्शित करने, अलग-अलग आइटम एक प्रतिनिधि द्वारा तैयार कर रहे हैं:

docs for QStyledItemDelegate थोड़ा और विस्तार प्रदान करते हैं। साथ ही, जब कोई आइटम संपादित होता है, तो यह एक संपादक विजेट प्रदान करता है, जो संपादन के दौरान आइटम दृश्य के शीर्ष पर रखा जाता है। QStyledItemDelegate सभी क्यूटी आइटम दृश्यों के लिए डिफ़ॉल्ट प्रतिनिधि है, और उन्हें बनाए जाने पर पर स्थापित किया गया है।

संक्षेप में, अगर आप आइटम दृश्य (बस नहीं एक पेड़ देखने के लिए, लेकिन टेबल और सूचियों भी) में से किसी के अंतर्निहित यांत्रिकी समझने के लिए चाहते हैं, QStyledItemDelegate अध्ययन करते हैं।

qstyleditemdleegate.cpp में विधि on line 419 of the doxygenated code base परिभाषित किया गया है। आइए आखिरी दो लाइनों को देखें:

QStyle *style = widget ? widget->style() : QApplication::style(); 
    style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget); 

दो चीजें यहां हो रही हैं। सबसे पहले, शैली सेट की गई है - आम तौर पर QApplication.style() पर। दूसरा, उस शैली को चित्रित करने के लिए उस शैली की drawControl() विधि लागू की गई है। और बस। यह सचमुच QStyledItemDelegate.paint() की अंतिम पंक्ति है!

इसलिए, यदि आप वास्तव में यह जानना चाहते हैं कि डिफ़ॉल्ट प्रतिनिधि कैसे चित्रकारी कर रहा है, तो हमें वास्तव में शैली का अध्ययन करना है, जो सभी वास्तविक काम कर रहा है। यही वह है जो हम इस दस्तावेज़ के बाकी हिस्सों में करेंगे।

II। QStyle: प्रतिनिधि को अपनी शैली क्या देता है?

जब क्यूटी का उपयोग करके कुछ भी प्रदर्शित होता है, तो इसे सिस्टम-विशिष्ट तरीके से चुना गया कुछ शैली के अनुसार खींचा जाता है, जब आपने QApplication को तत्काल बनाया था। the docs for QStyle से:

QStyle वर्ग एक सार आधार वर्ग कि देखो और एक जीयूआई के लग रहा है समाहित है। क्यूटी में QStyle उप-वर्गों का एक सेट होता है जो Q12 (QWindowsStyle, QMacStyle, QMotifStyle इत्यादि) द्वारा समर्थित विभिन्न प्लेटफ़ॉर्म की शैलियों अनुकरण करता है। डिफ़ॉल्ट रूप से, इन शैलियों को QtGui लाइब्रेरी में बनाया गया है।

क्यूटी में, आपको src/gui/styles/N.cpp में शैली एन के लिए स्रोत कोड मिलेगा।

प्रत्येक शैली में जीयूआई में सब कुछ खींचने के लिए उपयोग किए जाने वाले प्राथमिक संचालन के कार्यान्वयन होते हैं, पेड़ दृश्यों से ड्रॉपडाउन मेनू तक। QWindowsStyle जैसे मानक शैलियों, QCommonStyle से उनके अधिकांश तरीकों का उत्तराधिकारी है। प्रत्येक विशेष शैली में आम तौर पर उस सामान्य आधार से मामूली विचलन शामिल होते हैं। इसलिए, qcommonstyle.cpp का एक करीबी अध्ययन आधार कार्यक्षमता को प्रकट करेगा जो क्यूटी डेवलपर्स को जीयूआई के सभी हिस्सों को चित्रित करने के लिए उपयोगी पाया गया है। इसका महत्व अतिस्तरीय करना मुश्किल है।

इस प्रकार, हम दृश्य वस्तुओं को चित्रित करने के लिए प्रासंगिक भागों की जांच करेंगे।

III। QStyle.drawControl():, प्रतिनिधि

के रूप में ऊपर उल्लेख किया है पर एंडोस्कोपी प्रदर्शन qcommonstyle.cpp में एक दृश्य के drawControl() के कार्यान्वयन की जांच की आवश्यकता है ड्राइंग के बुनियादी यांत्रिकी समझने, एक कार्यान्वयन है कि क्या इस प्रकार में पर लाइन 1197. नोट शुरू होता है, जब मैं एक फ़ाइल नाम का उल्लेख किए बिना एक लाइन नंबर का संदर्भ देता हूं, तो सम्मेलन द्वारा मैं qcommonstyle.cpp in the doxygenated code base का जिक्र कर रहा हूं।

documentation for QStyle.drawControl() शिक्षाप्रद है:

QStyle.drawControl (तत्व, विकल्प, चित्रकार)

पैरामीटर:

  • तत्व - QStyle।ControlElement

  • विकल्प - QtGui.QStyleOption

  • चित्रकार - PySide.QtGui.QPainter

शैली विकल्प विकल्प द्वारा निर्दिष्ट के साथ प्रदान की चित्रकार के साथ दिया तत्व खींचता .... विकल्प पैरामीटर QStyleOption ऑब्जेक्ट के लिए एक सूचक है और वांछित तत्व को आकर्षित करने के लिए आवश्यक सभी जानकारी शामिल है।

फोन करने वाले drawControl() बताता तत्व किस प्रकार यह है कि यह एक QStyle.ControlElement झंडा पास करके आकर्षित करने के लिए कोशिश कर रहा है। नियंत्रण तत्व एक विंडो के उच्च-स्तरीय घटक होते हैं जो उपयोगकर्ता को जानकारी प्रदर्शित करते हैं: चेकबॉक्स, पुशबूटन और मेनू आइटम जैसी चीजें। नियंत्रण तत्वों के सभी यहाँ enumerated हैं:

http://pyqt.sourceforge.net/Docs/PyQt4/qstyle.html#ControlElement-enum

याद QStyledItemDelegate.paint() करने के लिए कॉल में भेजा नियंत्रण तत्व CE_ItemViewItem था, जो केवल एक आइटम एक आइटम दृश्य के अंदर प्रदर्शित किया जा सकता है। QCommonStyle.drawControl() के भीतर, CE_ItemViewItem मामले लाइन 2153. पर शुरू होता है की खुदाई करते

ए subElementRect():। आकार मायने रखती है

यह आकार और प्रत्येक आइटम के लेआउट सही पाने के लिए महत्वपूर्ण है। यह पहली बात है drawControl() गणना करता है। इस जानकारी को प्राप्त करने के लिए, यह subElementRect() (लाइन 2313 पर परिभाषित किया गया है, और पहले लाइन 2158 पर बुलाया गया) का आह्वान करता है। उदाहरण के लिए, हमने:

QRect textRect = subElementRect(SE_ItemViewItemText, vopt, widget); 

पहला तर्क इस मामले SE_ItemViewItemText, एक QStyle.SubElement झंडा है। शैली उपखंड नियंत्रण तत्वों के घटक भागों का प्रतिनिधित्व करते हैं। दृश्य में प्रत्येक आइटम में तीन संभावित उपखंड हैं: चेकबॉक्स, आइकन और टेक्स्ट; जाहिर है, SE_ItemViewItemText उपखंड टेक्स्ट का प्रतिनिधित्व करता है। सभी संभव उसके उप-तत्व यहां उनका वर्णन कर रहे हैं: हमारे SE_ItemViewItemText मामले लाइन पर शुरू होता है 3015.

ध्यान दें कि subElementRect() रिटर्न एक QRect है, जो एक परिभाषित करता है:

http://pyqt.sourceforge.net/Docs/PyQt4/qstyle.html#SubElement-enum

subElementRect() विधि subelement गणन में सभी मामलों में शामिल है पूर्णांक परिशुद्धता का उपयोग कर विमान में आयताकार, और चार पूर्णांक (बाएं, शीर्ष, चौड़ाई, ऊंचाई) के साथ बनाया जा सकता है। उदाहरण के लिए r1 = QRect(100, 200, 11, 16)। यह एक उपखंड के लिए, इसके आकार के साथ-साथ x, y स्थिति निर्दिष्ट करता है जहां इसे व्यूपोर्ट में चित्रित किया जाएगा।

subElementRect() वास्तव में वास्तविक कार्य करने के लिए viewItemLayout() (लाइन 999 पर परिभाषित) को कॉल करता है, जो दो-चरणीय प्रक्रिया है। सबसे पहले, viewItemLayout()viewItemSize() का उपयोग करके उपखंडों की ऊंचाई और चौड़ाई की गणना करता है। दूसरा, यह उपखंड की एक्स और वाई स्थिति की गणना करता है। आइए इन कार्यों में से प्रत्येक को बदले में देखें।

1।viewItemLayout(): चौड़ाई और उसके उप-तत्व

लाइन 1003 पर शुरू की ऊंचाई की गणना, viewItemLayout() कॉल viewItemSize() है, जो ऊंचाई और चौड़ाई एक subelement के लिए आवश्यक की गणना करता है (लाइन 838 पर परिभाषित)।

viewItemSize() कहाँ शीर्षक पट्टी की ऊंचाई जैसी चीजों के लिए डिफ़ॉल्ट नंबर प्राप्त करता है? यह पिक्सेल मीट्रिक का प्रांत है। एक पिक्सेल मीट्रिक एक शैली-निर्भर आकार है जो एकल पिक्सेल मान द्वारा दर्शाया जाता है। उदाहरण के लिए, Style.PM_IndicatorWidth एक चेक बॉक्स सूचक की चौड़ाई देता है, और QStyle.PM_TitleBarHeight रिटर्न आपके आवेदन की शैली के लिए शीर्षक पट्टी ऊंचाई। सभी अलग QStyle.PixelMetric रों यहां उनका वर्णन कर रहे हैं:

http://pyqt.sourceforge.net/Docs/PyQt4/qstyle.html#PixelMetric-enum

आप किसी एक पिक्सेल मीट्रिक का उपयोग QStyle.pixelMetric(), जो viewItemSize() में एक बहुत प्रयोग किया जाता है का मूल्य प्राप्त कर सकते हैं। pixelMetric() के पहले इनपुट गणन में QStyle.PixelMetric रों से एक है। qcommonstyle.cpp में pixelMetric() के कार्यान्वयन लाइन 4367.

उदाहरण के लिए शुरू होता है, viewItemSize() चौड़ाई और चेकबॉक्स की ऊंचाई की गणना करता है (यदि आवश्यक) का उपयोग करते हुए निम्नलिखित:

return QSize(proxyStyle->pixelMetric(QStyle::PM_IndicatorWidth, option, widget), 
    proxyStyle->pixelMetric(QStyle::PM_IndicatorHeight, option, widget)); 

ध्यान दें कि pixelMetric() बस में नहीं प्रयोग किया जाता है viewItemSize(), लेकिन सर्वव्यापी है। यह माउस के लिए खिड़की सीमाओं से, कई जीयूआई तत्वों की मीट्रिक गुण गणना करने के लिए प्रयोग किया जाता है, और qcommonstyle.cpp भर peppered है। असल में, जब भी आपको यह पता होना चाहिए कि आपकी शैली कुछ ग्राफिकल तत्वों के लिए कितनी पिक्सेल का उपयोग करती है जिसका आकार बदलता नहीं है (चेकबॉक्स की तरह), शैली पिक्सेल मेट्रिक्स पर कॉल करेगी।

2. viewItemLayout(): रूबिक का क्यूब उसके उप-तत्व x/y पदों

viewItemLayout() के दूसरे भाग उसके उप-तत्व जिसका चौड़ाई और ऊंचाई सिर्फ गणना की गई के लेआउट के आयोजन के लिए समर्पित है पाने के लिए। यही है, इसे जैसे textRect में मान भरने के लिए अपने एक्स और वाई पदों को खोजने की आवश्यकता है। दृश्यों के सामान्य सेटअप के आधार पर उपखंडों का अलग-अलग आयोजन किया जाएगा (उदाहरण के लिए, चाहे यह दाएं बाएं या बाएं-दाएं ओरिएंटेड हों)। इसलिए, viewItemLayout() ऐसे कारकों के आधार पर प्रत्येक उपखंड की अंतिम विश्राम स्थिति की गणना करता है।

यदि आपको कभी भी कस्टम प्रतिनिधि में sizeHint() को पुन: कार्यान्वित करने के बारे में सुराग की आवश्यकता है, तो subElementRect() युक्तियों और युक्तियों का एक उपयोगी स्रोत हो सकता है। विशेष रूप से, viewItemSize() उपयोगी छोटी-मोटी बातें और प्रासंगिक पिक्सेल मैट्रिक्स आप क्वेरी करने के लिए जब तुम करीब से डिफ़ॉल्ट मिलान करने के लिए एक कस्टम दृश्य चाहते हैं चाहते हो सकता है शामिल होने की संभावना है।

एक बार QRect एस टेक्स्ट, आइकन और चेकबॉक्स सबलेमेंट्स के लिए गणना की जाती है, drawControl() चाल चलती है, और आखिर में आकर्षित करना शुरू होता है।

बीपृष्ठभूमि का रंग: आदिम

पहले पृष्ठभूमि रही मद (लाइन 2163) के लिए में भर जाता है:

drawPrimitive(PE_PanelItemViewItem, option, painter); 

यह QStyle.drawControl() करने के लिए कॉल की तरह एक बहुत कुछ है, लेकिन पहले तर्क एक नियंत्रण नहीं है तत्व, लेकिन आदिम तत्व (पीई)। जैसे drawControl() एक बड़ी फैलाने वाली विधि है जो सभी उच्च स्तरीय नियंत्रण तत्वों के चित्र को नियंत्रित करती है, QStyle.drawPrimitive() एक जीयूआई (जैसे आइटम दृश्य में आयताकार पृष्ठभूमि) में निचले स्तर के आदिम ग्राफिकल तत्वों को खींचती है। ये निचले स्तर इकाइयों, आदिम तत्वों, यहां उनका वर्णन कर रहे हैं:

http://pyqt.sourceforge.net/Docs/PyQt4/qstyle.html#PrimitiveElement-enum

डॉक्स, कहते हैं कि "एक आदिम तत्व एक आम जीयूआई तत्व, जैसे कि चेकबॉक्स सूचक या बटन बेवल के रूप में है।" उदाहरण के लिए, PE_PanelItemViewItem आदिम तत्व "[टी] वह आइटम आइटम में किसी आइटम के लिए पृष्ठभूमि है।"

प्रत्येक शैली में drawPrimitive() का कार्यान्वयन होना चाहिए, और हमारा 140 पृष्ठ पर शुरू होता है। इसके बाद, आप विस्तार से पता लगा सकते हैं कि यह अपने आदिम पेंट ऑपरेशंस को कैसे चलाता है। यह आपके कस्टम प्रतिनिधियों में अभ्यास में paint() कमांड का उपयोग करने के लिए संकेतों का एक उपयोगी स्रोत है।

का PE_PanelItemViewItem केस के लिए पुनर्मूल्यांकन लाइन 773 पर शुरू होता है। यह पहले आइटम की स्थिति के आधार पर उचित पृष्ठभूमि रंग का चयन करता है। यह आइटम के QStyle.StateFlag से पूछताछ करके करता है। option.state में राज्य झंडे शामिल हैं जो उस समय आइटम की स्थिति का वर्णन करते हैं (क्या यह सक्षम है, चयनित है, संपादित किया जा रहा है, आदि?)। इन राज्यों का उपयोग अभी भी पिछली छोर में नहीं किया जाता है, लेकिन आपके कस्टम प्रतिनिधियों में QStyledItemDelegate.paint() को पुन: कार्यान्वित करते समय आपको इसका उपयोग करने की आवश्यकता होगी। आप QStyle.StateFlag रों के गणन यहाँ पा सकते हैं:

http://pyqt.sourceforge.net/Docs/PyQt4/qstyle.html#StateFlag-enum

सही रंग उठा के बाद, drawPrimitive() तो QPainter.fillRect() का उपयोग करता है रंग (लाइन 786) के साथ उपयुक्त क्षेत्र को भरने के लिए:

p->fillRect(vopt->rect, vopt->backgroundBrush); 

QPainter.fillRect() आपके लिए कस्टम प्रतिनिधियों को लागू करते समय एक बहुत ही उपयोगी विधि है।

पृष्ठभूमि की देखभाल करने के बाद, drawControl() फिर चेकबॉक्स (लाइन 2165), फिर आइकन (लाइन 2185), और अंत में टेक्स्ट (लाइन 21 9 4) से शुरू होने वाली वस्तु को चित्रित करने के लिए आगे बढ़ता है। हम विस्तार से इस पर नहीं जाएंगे, लेकिन मैं संक्षेप में चर्चा करूँगा कि यह पाठ को कैसे आकर्षित करता है।

सी पाठ ड्राइंग: जा रहा पाखण्डी

पहले, आइटम की स्थिति पाठ के रंग निर्दिष्ट करने के लिए प्रयोग किया जाता है। यह अभी चर्चा की गई QStyle.StateFlags का उपयोग करता है। फिर एक कस्टम विधि viewItemDrawText() के लिए बाहर drawControl() किक पाठ ड्राइंग जिम्मेदारियों (लाइन 921 पर परिभाषित):

viewItemDrawText(painter, vopt, textRect); 

इस विधि पाठ आयत ऊपर (भाग एक) वर्णित पैरामीटर के रूप में चित्रकार, विकल्प में लेता है, और।नोट करें कि पैरामीटर पैरामीटर बहुत महत्वपूर्ण है: यह QStyleOption कक्षा है जिसके द्वारा सामग्री को शैली के भीतर पारित किया जाता है (इसमें आइकन, चेकस्टेट और टेक्स्ट गुण शामिल हैं)।

पाठ से विकल्प खींचने के बाद, इसे QtGui.QTextLine में शामिल किया गया है जो QtGui.QTextLayout में जोड़ा गया है। फाइनल, elided (यानी, शब्द रैप सेटिंग्स के आधार पर, इलिप्स के साथ) पाठ QPainter.drawText() (लाइन 983 देखें) द्वारा खींचा जाता है, जो क्यूटी के आदिम चित्रकला संचालन में से एक है।

फ्रैंकली viewItemDrawText() का एक अच्छा सौदा शब्द रैपिंग से निपटने में बिताया जाता है। यह वह जगह है जहां हम क्यूटी के कुछ हिस्सों में शामिल होना शुरू करते हैं कि कोई पायथन उपयोगकर्ता कभी देखने के लिए नहीं था, बहुत कम टिंकर। उदाहरण के लिए, यह QStackTextEngine कक्षा का उपयोग करता है। मैं आपको Google 'qstacktextengine pyqt' को प्रोत्साहित करता हूं कि यह देखने के लिए कि यह पाइथन उपयोगकर्ताओं के लिए कितनी बार आ गया है। यदि यह आपकी रूचि है, तो उस पर है!

IV। सारांश

आप डिफ़ॉल्ट प्रतिनिधि के लिए अंतर्निहित चित्रकला यांत्रिकी उपयोग करना चाहते हैं, तो आप एक फ़ाइल की एक 6000-लाइन जानवर qcommonstyle.cpp में QStyle.drawControl() के कार्यान्वयन का अध्ययन, खत्म हो जाएगा। यह अभ्यास आकार की गणना करने के लिए उपयोग की जाने वाली सटीक प्रक्रियाओं को समझने और वस्तुओं के मूल ग्राफिकल तत्वों को आकर्षित करने के लिए बहुत उपयोगी हो सकता है। कभी-कभी, हालांकि, यह जानवर डरावनी और अनुपयोगी हो सकता है, जैसे शब्द लपेटने से निपटने की बात आती है। उन मामलों में, आपको शायद अपने प्रतिनिधि के लिए वांछित कार्यक्षमता के कस्टम कार्यान्वयन को समझना होगा।

आखिरकार, अब हमने चीजों के काम के बारे में एक बड़ा चित्र देखा है, हम बेहतर तरीके से सराहना कर सकते हैं कि QStyle के लिए दस्तावेज़ कितना उपयोगी है, विशेष रूप से अनुभाग Styles in Item Views। वहां, हमें निम्नलिखित revelatory प्यार nugget मिलते हैं:

विचारों में वस्तुओं की पेंटिंग एक प्रतिनिधि द्वारा की जाती है। क्यूटी के डिफ़ॉल्ट प्रतिनिधि, QStyledItemDelegate, यह भी आइटम (और उनके उप-तत्व) की सीमांकन आयतों ... QStyledItemDelegate अपने आइटम पेंट है, यह CE_ItemViewItems ड्रॉ की गणना ... जब आइटम विचारों के ड्राइंग अनुकूलित करने के लिए एक शैली लागू करने के लिए प्रयोग किया जाता है, आप की जरूरत QCommonStyle (और किसी अन्य उप-वर्ग के कार्यान्वयन की जांच करें जिससे आपकी शैली विरासत में है)। इस तरह, आप यह पता लगाते हैं कि अन्य स्टाइल तत्व पहले से ही चित्रित हैं, और फिर आप को उन तत्वों की पेंटिंग को फिर से कार्यान्वित कर सकते हैं जिन्हें अलग-अलग खींचा जाना चाहिए।

तो मूल रूप से मूल पोस्ट का जवाब है, "उन्होंने क्या कहा।"

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