2012-10-24 4 views
5

Qt4 Model/View Programming을 배우기 시작했으며 초급 질문이 있습니다.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() 및 flags()를 다시 구현해야합니다.

+0

예, QSqlQueryModel에 대해 읽었지만 데이터베이스에 대한 쓰기 권한이 필요합니다. 그래서 QSqlTableModel부터 시작했습니다. 하지만이 예제에 감사드립니다! – Adam

관련 문제