2013-08-05 8 views
10

पृष्ठभूमि: मुझे QTableView के अंदर एक combobox का पूरा काम करने वाला उदाहरण नहीं मिल रहा है। इसलिए मैंने इस कोड को कई अन्य अधिक विपरीत उदाहरणों के आधार पर लिखा है। समस्या यह है कि, हालांकि, इस उदाहरण के लिए आपको सक्षम होने से पहले combobox पर डबल-क्लिक करने की आवश्यकता है, फिर आपको इसे छोड़ने के लिए फिर से क्लिक करना होगा। यह बहुत उपयोगकर्ता के अनुकूल नहीं है। यदि मैं QTableWidget का उपयोग कर गैर-मॉडल/दृश्य-वस्तु करता हूं, तो पहले क्लिक पर कंबोबॉक्स नीचे गिर जाता है।पीईक्यूटी - QTableView

प्रश्न: क्या कोई इसे देख सकता है और मुझे बता सकता है कि इसे QTableWidget जैसे प्रतिक्रिया देने के लिए क्या किया जाना चाहिए? अगर ऐसा कुछ भी है जो मैं कर रहा हूं वह अनावश्यक है, तो कृपया इसे भी इंगित करें। उदाहरण के लिए, क्या एप्लिकेशन शैली का संदर्भ देना बिल्कुल जरूरी है?

import sys 
from PyQt4 import QtGui, QtCore 

rows = "ABCD" 
choices = ['apple', 'orange', 'banana'] 

class Delegate(QtGui.QItemDelegate): 
    def __init__(self, owner, items): 
     super(Delegate, self).__init__(owner) 
     self.items = items 
    def createEditor(self, parent, option, index): 
     self.editor = QtGui.QComboBox(parent) 
     self.editor.addItems(self.items) 
     return self.editor 
    def paint(self, painter, option, index): 
     value = index.data(QtCore.Qt.DisplayRole).toString() 
     style = QtGui.QApplication.style() 
     opt = QtGui.QStyleOptionComboBox() 
     opt.text = str(value) 
     opt.rect = option.rect 
     style.drawComplexControl(QtGui.QStyle.CC_ComboBox, opt, painter) 
     QtGui.QItemDelegate.paint(self, painter, option, index) 
    def setEditorData(self, editor, index): 
     value = index.data(QtCore.Qt.DisplayRole).toString() 
     num = self.items.index(value) 
     editor.setCurrentIndex(num) 
    def setModelData(self, editor, model, index): 
     value = editor.currentText() 
     model.setData(index, QtCore.Qt.DisplayRole, QtCore.QVariant(value)) 
    def updateEditorGeometry(self, editor, option, index): 
     editor.setGeometry(option.rect) 

class Model(QtCore.QAbstractTableModel): 
    def __init__(self): 
     super(Model, self).__init__() 
     self.table = [[row, choices[0]] for row in rows] 
    def rowCount(self, index=QtCore.QModelIndex()): 
     return len(self.table) 
    def columnCount(self, index=QtCore.QModelIndex()): 
     return 2 
    def flags(self, index): 
     return QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable 
    def data(self, index, role): 
     if role == QtCore.Qt.DisplayRole: 
      return self.table[index.row()][index.column()] 
    def setData(self, index, role, value): 
     if role == QtCore.Qt.DisplayRole: 
      self.table[index.row()][index.column()] = value 

class Main(QtGui.QMainWindow): 
    def __init__(self, parent=None): 
     super(Main, self).__init__(parent) 
     self.model = Model() 
     self.table = QtGui.QTableView() 
     self.table.setModel(self.model) 
     self.table.setItemDelegateForColumn(1, Delegate(self, ["apple", "orange", "banana"])) 
     self.setCentralWidget(self.table) 
     self.setWindowTitle('Delegate Test') 
     self.show() 

if __name__ == '__main__': 
    app = QtGui.QApplication(sys.argv) 
    main = Main() 
    app.exec_() 
+0

आप करने के लिए [इस सवाल] मेरा उत्तर मिल सकता है (http://stackoverflow.com/questions/17615997/pyqt-how-to-set-qcombobox-in- एक-टेबल-व्यू-उपयोग-qitemdelegate) सहायक। –

+1

धन्यवाद, अब मैं देखता हूं कि 'पेंट' ओवरराइड अनावश्यक है, और मुझे 'ओपन पर्सिस्टेंट एडिटर' की आवश्यकता है। लेकिन 'openPersistentEditor' को कॉल करना मॉडल/व्यू के उद्देश्य को हराने के लिए लगता है अगर मुझे मॉडल के बाहर से कॉल करने की आवश्यकता है। इसके अलावा, यह उन सभी comboboxes को आकर्षित करने में अक्षम लगता है जब आप केवल एक समय में एक ही संचालित कर सकते हैं। क्या डबल-क्लिक आवश्यकता से छुटकारा पाने का कोई तरीका है, इसलिए यह सेल चयन पर दिखाई देता है? – user2120303

+0

आपको इसे मॉडल से कॉल करने की आवश्यकता नहीं है। यदि आवश्यक हो तो मॉडल बदलने और संपादक को आमंत्रित करने के लिए आप किसी अन्य ऑब्जेक्ट (उदा। अपने उप-वर्गीकृत दृश्य या फ़ॉर्म) का उपयोग कर सकते हैं। दूसरे प्रश्न के लिए, 'view-> चयन मॉडल()' के अपने चयन में 'चयन बदलें' सिग्नल को कनेक्ट करें। चयनित स्लॉट में इस स्लॉट ओपन एडिटर में और यदि आवश्यक हो तो पिछले संपादकों को बंद करें। –

उत्तर

5

QTableWiget.setCellWidget

import sys 
from PyQt4 import QtGui 
app = QtGui.QApplication(sys.argv) 
table = QtGui.QTableWidget(1,1) 
combobox = QtGui.QComboBox() 
combobox.addItem("Combobox item") 
table.setCellWidget(0,0, combobox) 
table.show() 
app.exec() 
+0

प्रश्न QTableView के अंदर कॉम्बो-बॉक्स के लिए पूछता है, QTableWidget नहीं। – ekhumoro

+0

@ekhumoro हाँ, मैंने देखा कि मैंने सोचा कि वह सिर्फ एक टेबल में विजेट प्राप्त करने का एक तरीका चाहता था। मैं शायद इस जवाब को हटा दूंगा। –

1

का उपयोग करके आप जब दृश्य संपादक को प्रदर्शित करता है को समायोजित करने की कोशिश कर रहे हैं, तो आप के रूप में QAbstractItemView में परिभाषित संपादित ट्रिगर बदलने की जरूरत है। डिफ़ॉल्ट डबलक्लिक पर संपादित किया गया है, लेकिन मुझे लगता है कि आप QAbstractItemView.CurrentChanged के बाद क्या कर रहे हैं। myView.setEditTrigger()

-1

बुला अगर कोई रुचि रखता है के द्वारा इसे सेट करें, नीचे एक ही उदाहरण PyQt5 और अजगर 3. प्रमुख अपडेट के लिए संशोधित किया है में शामिल हैं:

  • अजगर 3: super().__init__()
  • PyQt5: अधिकांश वर्गों QtWidgets में हैं ; इनपुट तर्क आदेश करने के लिए बदल: QtGui इस उदाहरण
  • Model.setData के लिए की जरूरत नहीं है index, value, role, और TrueNone
  • कॉम्बो बॉक्स choices और टेबल अब Main अंदर निर्दिष्ट सामग्री के बजाय वापस आ; इस Delegate और Model अधिक सामान्य बनाता है
from PyQt5 import QtWidgets, QtCore 

class Delegate(QtWidgets.QItemDelegate): 
    def __init__(self, owner, choices): 
     super().__init__(owner) 
     self.items = choices 
    def createEditor(self, parent, option, index): 
     self.editor = QtWidgets.QComboBox(parent) 
     self.editor.addItems(self.items) 
     return self.editor 
    def paint(self, painter, option, index): 
     value = index.data(QtCore.Qt.DisplayRole) 
     style = QtWidgets.QApplication.style() 
     opt = QtWidgets.QStyleOptionComboBox() 
     opt.text = str(value) 
     opt.rect = option.rect 
     style.drawComplexControl(QtWidgets.QStyle.CC_ComboBox, opt, painter) 
     QtWidgets.QItemDelegate.paint(self, painter, option, index) 
    def setEditorData(self, editor, index): 
     value = index.data(QtCore.Qt.DisplayRole) 
     num = self.items.index(value) 
     editor.setCurrentIndex(num) 
    def setModelData(self, editor, model, index): 
     value = editor.currentText() 
     model.setData(index, QtCore.Qt.DisplayRole, QtCore.QVariant(value)) 
    def updateEditorGeometry(self, editor, option, index): 
     editor.setGeometry(option.rect) 

class Model(QtCore.QAbstractTableModel): 
    def __init__(self, table): 
     super().__init__() 
     self.table = table 
    def rowCount(self, parent): 
     return len(self.table) 
    def columnCount(self, parent): 
     return len(self.table[0]) 
    def flags(self, index): 
     return QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable 
    def data(self, index, role): 
     if role == QtCore.Qt.DisplayRole: 
      return self.table[index.row()][index.column()] 
    def setData(self, index, value, role): 
     if role == QtCore.Qt.EditRole: 
      self.table[index.row()][index.column()] = value 
     return True 

class Main(QtWidgets.QMainWindow): 
    def __init__(self, parent=None): 
     super().__init__(parent) 
     # set combo box choices: 
     choices = ['apple', 'orange', 'banana'] 
     # create table data: 
     table = [] 
     table.append(['A', choices[0]]) 
     table.append(['B', choices[0]]) 
     table.append(['C', choices[0]]) 
     table.append(['D', choices[0]]) 
     # create table view: 
     self.model  = Model(table) 
     self.tableView = QtWidgets.QTableView() 
     self.tableView.setModel(self.model) 
     self.tableView.setItemDelegateForColumn(1, Delegate(self,choices)) 
     # make combo boxes editable with a single-click: 
     for row in range(len(table)): 
      self.tableView.openPersistentEditor(self.model.index(row, 1)) 
     # initialize 
     self.setCentralWidget(self.tableView) 
     self.setWindowTitle('Delegate Test') 
     self.show() 

if __name__ == '__main__': 
    import sys 
    app = QtWidgets.QApplication(sys.argv) 
    main = Main() 
    app.exec_()