2009-06-04 20 views
28

मैं एक पीईक्यूटी एप्लीकेशन लिख रहा हूं और कस्टम सूची दृश्य बनाने में कुछ परेशानी हो रही है। मैं सूची में मनमानी विजेट (विशेष रूप से एक कस्टम विजेट) शामिल करना चाहता हूं। मैं इसे किस तरह लूं?कस्टम आइटम और कस्टम आइटम विजेट्स के साथ QListView/QListWidget

ऐसा लगता है कि विकल्प स्क्रॉलबार में लिपटे एक टेबल या ग्रिड व्यू बनाना होगा। हालांकि, मैं मॉडल/व्यू दृष्टिकोण के साथ-साथ घोंसले (पेड़-दृश्य) का निर्माण करने में सक्षम होना चाहता हूं, जो अंतर्निहित हैंडल का समर्थन करता है।

स्पष्टीकरण के लिए, कस्टम विजेट इंटरैक्टिव (बटन होते हैं) हैं, इसलिए समाधान को विजेट पेंट करने से अधिक की आवश्यकता होती है।

उत्तर

28

मुझे लगता है कि आपको QItemDelegate उपclass करने की आवश्यकता है।

QItemDelegate QAbstractItemView उपवर्गों के आधार पर कस्टम प्रदर्शन सुविधाओं और आइटम विचारों के लिए संपादक विगेट्स प्रदान करने के लिए इस्तेमाल किया जा सकता। इस उद्देश्य के लिए प्रतिनिधि का उपयोग प्रदर्शित करने और संपादन तंत्र को अनुकूलित और स्वतंत्र रूप से मॉडल और दृश्य से विकसित करने की अनुमति देता है।

यह कोड क्यूटी के उदाहरणों, धार आवेदन से लिया गया है।

class TorrentViewDelegate : public QItemDelegate 
{ 
    Q_OBJECT 
public: 
    inline TorrentViewDelegate(MainWindow *mainWindow) : QItemDelegate(mainWindow) {} 

    inline void paint(QPainter *painter, const QStyleOptionViewItem &option, 
         const QModelIndex &index) const 
    { 
     if (index.column() != 2) { 
      QItemDelegate::paint(painter, option, index); 
      return; 
     } 

     // Set up a QStyleOptionProgressBar to precisely mimic the 
     // environment of a progress bar. 
     QStyleOptionProgressBar progressBarOption; 
     progressBarOption.state = QStyle::State_Enabled; 
     progressBarOption.direction = QApplication::layoutDirection(); 
     progressBarOption.rect = option.rect; 
     progressBarOption.fontMetrics = QApplication::fontMetrics(); 
     progressBarOption.minimum = 0; 
     progressBarOption.maximum = 100; 
     progressBarOption.textAlignment = Qt::AlignCenter; 
     progressBarOption.textVisible = true; 

     // Set the progress and text values of the style option. 
     int progress = qobject_cast<MainWindow *>(parent())->clientForRow(index.row())->progress(); 
     progressBarOption.progress = progress < 0 ? 0 : progress; 
     progressBarOption.text = QString().sprintf("%d%%", progressBarOption.progress); 

     // Draw the progress bar onto the view. 
     QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter); 
    } 
}; 

मूल रूप से के रूप में आप देख सकते हैं यह जाँच करता है, तो स्तंभ रंगा जाना एक विशिष्ट सूचकांक की है, इसलिए यह एक प्रगति बार पेंट करता है, तो। मुझे लगता है कि आप इसे थोड़ा छोटा कर सकते हैं और QStyleOption का उपयोग करने के बजाय आप अपने विजेट का उपयोग कर सकते हैं।

संपादित करें: setItemDelegate का उपयोग करके अपने आइटम प्रतिनिधि को अपने QListView के साथ सेट करना न भूलें।

अपने प्रश्न की जांच करते समय मैंने this थ्रेड पर ठोकर खाई है, जो कि QItemDelegate का उपयोग करके एक कस्टम विजेट को पेंट करने का तरीका बताता है, मुझे विश्वास है कि इसमें आपकी सारी जानकारी हो सकती है।

+0

पोस्ट के लिए धन्यवाद, मैं और अधिक कल इस पर गौर करेंगे। क्या आप विस्तृत विजेट के साथ QStyleOption ड्राइंग को बदलने के बारे में विस्तार से बता सकते हैं? –

+0

अच्छी तरह से यह QItemDelegate की पेंट विधि में प्रदान किए गए QPainter के साथ अपने विजेट को पेंट करने का मामला है। मैंने एक उपयोगी लिंक शामिल करने के लिए अपनी पोस्ट संपादित की है। –

+0

ठीक है, मैं इस तकनीक का उपयोग कर किसी न किसी काम कर सकता हूं। लेकिन मुद्दा "मनमाना विजेट" पहलू है - मेरे पास एक कंपाउंड विजेट है जिसमें बटन, आदि शामिल हैं, जो इंटरैक्टिव हैं - इसलिए उन्हें सूची में शारीरिक रूप से रखा जाना चाहिए या उपयोगकर्ता उन पर क्लिक करने में सक्षम नहीं है। अगर मैं गलत हूं तो मुझे सही करें, लेकिन यह केवल एक निष्क्रिय विजेट खींच जाएगा। –

2

असिस्ट कहते हैं, कि:

void QTableWidget::setCellWidget (int row, int column, QWidget * widget) 

सेट निर्धारित विजेट दी गई पंक्ति और कॉलम के कक्ष में प्रदर्शित करने के लिए, मेज पर विजेट के स्वामित्व गुजर। यदि सेल विजेट ए को सेल विजेट बी के साथ प्रतिस्थापित किया गया है, तो सेल विजेट ए हटा दिया जाएगा।

और QAbstractItemView वंशजों में से अधिकांश में इस विधि के अनुरूप हैं।

आपको क्यू *** को उप-वर्ग करना होगा जब आप संपादक विजेट को केवल तब दिखाई दें जब आप EditTrigger को हिट करते हैं, फिर गायब हो जाएं और प्रतिनिधि को किसी भी तरह से दृश्य आइटम प्रस्तुत करने दें।

यदि मैं सही करता हूं, तो आप हर समय आइटम दृश्य में नियंत्रण देखना चाहते हैं और संपादन मोड में प्रवेश करने की आवश्यकता के बिना नियंत्रण हिट करने में सक्षम होना चाहते हैं और प्रतीक्षा करते हैं जबकि प्रतिनिधि संपादक बनाता है और अपना राज्य सेट करता है, इसलिए आपको बनाने की आवश्यकता नहीं है विशिष्ट प्रतिनिधि, बस दृश्य के आइटम में विजेट सेट करें।

+0

दुर्भाग्यवश ऐसे फ़ंक्शन केवल 'QTableWidget',' QTreeWidget' और 'QListWidget' के लिए उपलब्ध हैं। कस्टम मॉडल के साथ दृश्य का उपयोग करते समय वे उपलब्ध नहीं हैं। –

+1

[डॉक्स] से (http://doc.qt.io/qt-5/qlistwidget.html#setItemWidget) "यह फ़ंक्शन केवल सूची विजेट आइटम के स्थान पर स्थिर सामग्री प्रदर्शित करने के लिए उपयोग किया जाना चाहिए। अगर आप चाहते हैं कस्टम गतिशील सामग्री प्रदर्शित करने या कस्टम संपादक विजेट को लागू करने के लिए, QListView और subclass QItemDelegate का उपयोग करें। " – Trilarion

1

एक और तरीका आप सूची में कस्टम आइटम जोड़ सकते हैं। इस उद्देश्य के लिए आपको नई कक्षा जोड़ने की जरूरत है। जैसा कि आप चाहते हैं इसे नाम दें, मैं इसे "myList" देता हूं, मुझे उम्मीद है कि आप परियोजना में नए आइटम कैसे जोड़ सकते हैं। :)

फिर इस नए फ्रेम में जितना चाहें उतना नियंत्रण जोड़ें।QLabels की तरह, QlineEdit आदि

फिर मुख्य वर्ग में यू एक listWidget नाम सूची या के रूप में आप चाहते हैं जोड़ने के लिए और निम्नलिखित कोड

MyList *myList = new MyList(); 
QListWidgetItem *item = new QListWidgetItem(); 
ui->list->insertItem(ui->list->size().height(),item); 
item->setSizeHint(QSize(50,30)); 
ui->list->setItemWidget(item,myList); 

बाद यू भी संकेत/स्लॉट का उपयोग करके आइटम गुण बदल सकते हैं बारे में है।

आशा है कि यह आपकी मदद करे ..!

+0

आइटम पर मेरी सूची हटाएं कौन नष्ट कर देता है? मैं इस नमूने में कोई स्वामित्व संबंधित कोड नहीं देख सकता। – Allex

+0

ठीक है, मैं जावा डेवलपर हूं और जावा कचरा संग्रह की परवाह करता है :) जो सी ++ का मेरा छोटा ज्ञान था –

3

@ इडान का उत्तर अच्छी तरह से काम करता है, लेकिन मैं एक सरल उदाहरण पोस्ट करूंगा जिसके साथ मैं आया था। यह आइटम प्रतिनिधि सिर्फ प्रत्येक आइटम के लिए एक काला आयताकार खींचता है।

class ItemDelegate : public QItemDelegate 
{ 
public: 
    explicit ItemDelegate(QObject *parent = 0) : QItemDelegate(parent) {} 
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 
    { 
     painter->fillRect(option.rect.adjusted(1, 1, -1, -1), Qt::SolidPattern); 
    } 
}; 

और फिर तुम सिर्फ सूची विजेट के लिए यह निर्धारित करने की आवश्यकता:

ui->listWidget->setItemDelegate(new ItemDelegate(ui->listWidget));