2012-10-24 15 views
5

मुझे क्यूटी 4 मॉडल/व्यू प्रोग्रामिंग सीखना शुरू हो गया है और मेरे पास शुरुआती प्रश्न है।QTableView में वर्चुअल कॉलम?

मैं साधारण आवेदन जो QTableView में SQLite तालिका दिखाने:

class Model(QtSql.QSqlTableModel): 
    def __init__(self, parent=None): 
     super(Model, self).__init__(parent) 
     self.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange) 

     self.setTable("test") 
     self.select() 

class App(QtGui.QMainWindow): 
    def __init__(self, model): 
     QtGui.QMainWindow.__init__(self) 

     self.ui = Ui_MainWindow() 
     self.ui.setupUi(self) 

     self.ui.tableView.setModel(model) 

if __name__ == "__main__": 
    myDb = QtSql.QSqlDatabase.addDatabase("QSQLITE") 
    myDb.setDatabaseName("test.db") 

    if not myDb.open(): 
     print 'FIXME' 

    model = Model() 

    app = QtGui.QApplication(sys.argv) 
    window = App(model) 
    window.show() 
    sys.exit(app.exec_()) 
यहाँ

कैसे डेटाबेस लगता है:

sqlite> create table test (a INTEGER, b INTEGER, c STRING); 
sqlite> insert into test VALUES(1, 2, "xxx"); 
sqlite> insert into test VALUES(6, 7, "yyy"); 

कुछ तो मैं हो रही है की तरह:

+---+---+-----+ 
| a | b | c | 
+---+---+-----+ 
| 1 | 2 | xxx | 
+---+---+-----+ 
| 6 | 7 | yyy | 
+---+---+-----+ 

में Model को संशोधित करना संभव हैवर्चुअल कॉलम की तरह कुछ? उदाहरण के लिए कुछ:

+---+---+-----+-----+ 
| a | b | sum | c | 
+---+---+-----+-----+ 
| 1 | 2 | 3 | xxx | 
+---+---+-----+-----+ 
| 6 | 7 | 13 | yyy | 
+---+---+-----+-----+ 

या शायद मुझे इसे किसी अन्य तरीके से करना चाहिए?

उत्तर

4

हाँ, आप यह कर सकते हैं। हालांकि @BrtH's answer प्रासंगिक है, मॉडल मुश्किल हैं और खो जाना आसान है। तो मैंने सोचा कि बिंदु उदाहरण में एक और मामला बेहतर होगा।

व्यक्तिगत रूप से, मैं QAbstractProxyModel से व्युत्पन्न प्रॉक्सी मॉडल का उपयोग करता हूं। लेकिन, आपके मामले में QSqlTableModel को पुन: कार्यान्वित करना भी व्यवहार्य है। नीचे आपके लक्ष्य के लिए एक कार्यान्वयन है। ध्यान दें कि, Model/View methodology की मूल बातें जानना आपके लिए आवश्यक है ताकि आप समझ सकें कि प्रत्येक विधि क्या करती है।

class Model(QtSql.QSqlTableModel): 
    def __init__(self, parent=None): 
     super(Model, self).__init__(parent) 
     self.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange) 

     self.setTable("test") 
     self.select() 


    def columnCount(self, parent=QtCore.QModelIndex()): 
     # this is probably obvious 
     # since we are adding a virtual column, we need one more column 
     return super(Model, self).columnCount()+1 


    def data(self, index, role=QtCore.Qt.DisplayRole): 
     if role == QtCore.Qt.DisplayRole and index.column()==2: 
      # 2nd column is our virtual column. 
      # if we are there, we need to calculate and return the value 
      # we take the first two columns, get the data, turn it to integer and sum them 
      # [0] at the end is necessary because pyqt returns value and a bool 
      # http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qvariant.html#toInt 
      return sum(self.data(self.index(index.row(), i)).toInt()[0] for i in range(2)) 
     if index.column() > 2: 
      # if we are past 2nd column, we need to shift it to left by one 
      # to get the real value 
      index = self.index(index.row(), index.column()-1) 
     # get the value from base implementation 
     return super(Model, self).data(index, role) 


    def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole): 
     # this is similar to `data` 
     if section==2 and orientation==QtCore.Qt.Horizontal and role==QtCore.Qt.DisplayRole: 
      return 'Sum' 
     if section > 2 and orientation==QtCore.Qt.Horizontal: 
      section -= 1 
     return super(Model, self).headerData(section, orientation, role) 


    def flags(self, index): 
     # since 2nd column is virtual, it doesn't make sense for it to be Editable 
     # other columns can be Editable (default for QSqlTableModel) 
     if index.column()==2: 
      return QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled 
     return QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsEditable 


    def setData(self, index, data, role): 
     # similar to data. 
     # we need to be careful when setting data (after edit) 
     # if column is after 2, it is actually the column before that 
     if index.column() > 2: 
      index = self.index(index.row(), index.column()-1) 
     return super(Model, self).setData(index, data, role) 
+0

इस उदाहरण के लिए धन्यवाद। यह बढ़िया काम करता है! – Adam

3

यह निश्चित रूप से संभव है। नीचे आपके कुछ कोड का एक उदाहरण है, जो आपके डेटा के लिए संशोधित है।

import sqlite3 

conn = sqlite3.connect('test.db') 


class MyTreeModel(QAbstractItemModel): 
    def __init__(self, parent=None): 
     super(MyTreeModel, self).__init__(parent) 

     c = conn.cursor() 
     c.execute("SELECT a, b, c FROM 'test'") 
     self.items = c.fetchall() 

     self.columns = ['a', 'b', 'sum', 'c'] 

    def columnCount(self, index): 
     return len(self.columns) 

    def rowCount(self, parent): 
     return len(self.items) 

    def data(self, index, role=Qt.DisplayRole): 
     if index.isValid(): 
      col= index.column() 
      spot = self.items[index.row()] 
      if role == Qt.DisplayRole: 
       if col == 0 or col == 1: 
        return self.items[index.row()][col] 
       elif col == 2: 
        return self.items[index.row()][0] + self.items[index.row()][1] 
       elif col == 3: 
        return self.items[index.row()][2] 

    def headerData(self, section, orientation, role=Qt.DisplayRole): 
     if orientation == Qt.Horizontal and role == Qt.DisplayRole: 
      return self.columns[section] 

    def index(self, row, col, index): 
     if not index.isValid(): 
      return self.createIndex(row, col) 
     else: 
      return QModelIndex() 

    def parent(self, child): 
     return QModelIndex() 

यह QTreeView के लिए एक मॉडल है, लेकिन मुझे लगता है कि आप इसे आसानी से अनुकूलित कर सकते हैं।
इन विधियों और मॉडल के बारे में अधिक जानकारी के लिए, http://srinikom.github.com/pyside-docs/PySide/QtCore/QAbstractItemModel.html देखें।

+0

मैं आपके उदाहरण में मॉडल को अपनाने की कोशिश कर रहा हूं। लेकिन मुझे 'rowCount' के साथ समस्या है। यह खाली 'self.items' की वजह से 0 लौटाता है। 'set_items' निष्पादित नहीं किया गया है, और मुझे यह फ़ंक्शन दस्तावेज़ में भी नहीं दिख रहा है। मुझे क्या याद आ रहा है – Adam

+0

आप कुछ भी याद नहीं कर रहे हैं, यह मेरी गलती है। 'set_items' एक 'आधिकारिक' फ़ंक्शन नहीं है, यह केवल कुछ है जो मैंने उपयोग किया क्योंकि मेरे कोड में मैंने मॉडल लोड होने के कुछ बार डेटा बदल दिया था। मैंने सीधे डाटाबेस से डेटा लोड करने के लिए जवाब संपादित किया है, लेकिन कुछ समय हो गया है क्योंकि मैंने डेटाबेस चीजें की हैं और मैंने कुछ भी परीक्षण नहीं किया है, इसलिए यह काम नहीं कर सकता है। – BrtH

+0

बहुत बहुत धन्यवाद। – Adam

1

क्या आपने QSqlQueryModel पर देखा है? यह किसी भी SQL क्वेरी के परिणाम दिखाने की अनुमति देता है। आपके उदाहरण के लिए कोड:

class Model(QtSql.QSqlQueryModel): 
    def __init__(self, parent=None): 
     super(Model, self).__init__(parent) 
     self.setQuery("SELECT a, b, a + b, c FROM test") 
     self.setHeaderData(0, QtCore.Qt.Horizontal, "a") 
     self.setHeaderData(1, QtCore.Qt.Horizontal, "b") 
     self.setHeaderData(2, QtCore.Qt.Horizontal, "sum") 
     self.setHeaderData(3, QtCore.Qt.Horizontal, "c") 

लेकिन ध्यान दें:

मॉडल केवल पढ़ने के लिए है डिफ़ॉल्ट रूप से। इसे पढ़ने-लिखने के लिए, आपको इसे उप-वर्गीकृत करना होगा और setData() और झंडे() को पुन: कार्यान्वित करना होगा।

+0

हां, मैं QSqlQueryModel के बारे में पढ़ रहा था लेकिन मुझे डेटाबेस तक पहुंच लिखने की भी आवश्यकता है। तो मैंने QSqlTableModel के साथ शुरू किया। लेकिन इस उदाहरण के लिए धन्यवाद! – Adam

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