2017-12-30 15 views
0

내 질문에 적합하지 않고 설명보다 혼란스러운 C++ 응답이있는 게시물이있는 곳에서 매달린 후 여기에서 묻습니다. QSqlTableModel을 서브 클래스로 만들려고하는데, 체크 박스가있는 부울 열이 필요하기 때문입니다. 전체 작업 프로그램은 다음과 같습니다pyqt5에서 QSqlTableModel을 서브 클래 싱하는 방법은 무엇입니까?

def setupModel(self): 
    print("-> setupModel") 
    # SET query 
    qry = QSqlQuery(self.gVar.db) 
    sql = "SELECT ID, name, unit, source, Import, ImportIfZero, visible FROM typeOfValue" 
    qry.prepare(sql) 
    qry.exec_(sql) 
    self.tableView_typeOfValues_Model.setQuery(qry) 

하지만 오류를 발견

from PyQt5.QtWidgets import * 
from PyQt5.QtCore import * 
from PyQt5.QtGui import * 
from PyQt5.QtSql import * 
import sys 

class ImportFilter (QDialog): 
    def __init__(self): 
     super().__init__() 
     self.initUI() 

    def initUI(self): 
     print("Welcome to StandardDialog") 
     # Load the Window 
     #self.ui = uic.loadUi("ImportFilter.ui",self) 
     #self.ui.setModal(True) 
     self.buttonBox = QDialogButtonBox() 
     self.tableView_typeOfValues = QTableView() 
     layout = QVBoxLayout() 
     layout.addWidget(self.buttonBox) 
     layout.addWidget(self.tableView_typeOfValues) 
     self.setLayout(layout) 

     # Init Environmment 
     self.db = createConnection() 

     # create Models 
     self.setupModel() 

     #setup Views 
     self.setupView() 

     # connect Signals 
     self.buttonBox.clicked.connect(self.pushButton_Box_clicked) 

     self.show() 
     print("<- initUI") 

    def setupView(self): 
     print("-> setupView") 
     self.tableView_typeOfValues.setModel(self.tableView_typeOfValues_Model) 
     self.tableView_typeOfValues.setColumnWidth(0,10) 
     self.tableView_typeOfValues.setColumnWidth(1,130) 
     self.tableView_typeOfValues.setColumnWidth(2,130) 
     self.tableView_typeOfValues.setColumnWidth(3,60) 
     self.tableView_typeOfValues.setColumnWidth(4,60) 
     self.tableView_typeOfValues.setColumnWidth(5,60) 
     self.tableView_typeOfValues.setColumnWidth(6,60) 

     self.tableView_typeOfValues.hideColumn(0) 
     self.tableView_typeOfValues.hideColumn(3) 
     print("<- setupView") 

    def setupModel(self): 
     print("-> setupModel") 
     # own model 
     self.tableView_typeOfValues_Model = ImportSqlTableModel() 
     print(" tables:", self.db.tables()) 
     print(' Before .setTable("typeOfValue") and select()') 
     self.tableView_typeOfValues_Model.info() 
     self.tableView_typeOfValues_Model.setTable("typeOfValue") 
     self.tableView_typeOfValues_Model.setEditStrategy(QSqlTableModel.OnFieldChange) 
     self.tableView_typeOfValues_Model.select() 
     print(' After .setTable("typeOfValue") and select()') 
     self.tableView_typeOfValues_Model.info() 
     self.headerData() 
     print(" Table:",self.tableView_typeOfValues_Model.tableName()) 
     print(" count:",self.tableView_typeOfValues_Model.rowCount()) 

     self.tableView_typeOfValues_Model.info() 
     print("<- setupModel") 

    def setupModelQRY(self): 
     print("-> setupModel with Query") 
     # works so far 
     #self.tableView_typeOfValues_Model = QSqlTableModel() # edit but no checkboxes 
     self.tableView_typeOfValues_Model = ImportSqlTableModel(self.db) # no edit 
     # SET query 
     qry = QSqlQuery(self.db) 
     sql = "SELECT ID, name, unit, source, Import, ImportIfZero, visible FROM typeOfValue" 
     qry.prepare(sql) 
     qry.exec_(sql) 
     self.tableView_typeOfValues_Model.setQuery(qry) 
     self.tableView_typeOfValues_Model.select() 
     print(" Filter:",self.tableView_typeOfValues_Model.filter()) 
     print(" SELECT:", self.tableView_typeOfValues_Model.selectStatement()) 
     self.tableView_typeOfValues_Model.setEditStrategy(QSqlTableModel.OnFieldChange) 
     print("<- setupModel") 

    def headerData(self): 
     print("-> headerData") 
     self.tableView_typeOfValues_Model.setHeaderData(0,Qt.Horizontal, "ID") 
     self.tableView_typeOfValues_Model.setHeaderData(1,Qt.Horizontal, "name") 
     self.tableView_typeOfValues_Model.setHeaderData(2,Qt.Horizontal, "unit") 
     self.tableView_typeOfValues_Model.setHeaderData(3,Qt.Horizontal, "source") 
     self.tableView_typeOfValues_Model.setHeaderData(4,Qt.Horizontal, "Import") 
     self.tableView_typeOfValues_Model.setHeaderData(5,Qt.Horizontal, "ImportIfZero") 
     self.tableView_typeOfValues_Model.setHeaderData(6,Qt.Horizontal, "visible") 
     print("<- headerData") 


    ################################################################################################### 
    #      functions 
    ################################################################################################### 
    def pushButton_Box_clicked(self,signal): 
     print("okButtonClicked") 
     print("buttonBox_clicked",signal) 
     self.tableView_typeOfValues_Model.submitAll() 
     self.exitcode = "ok, but not implemented" 
     sys.exit() 

    def returnCode(self): 
     return self.exitcode 

####################################################################################################################### 
#            C L A S S 
####################################################################################################################### 

class ImportSqlTableModel(QSqlTableModel): 
    def __init__(self): 
     super(ImportSqlTableModel, self).__init__() 
     print("-> ImportSqlTableModel.__init__:") 
     self.booleanSet =[4,5,6] 
     self.readOnlySet = [1] 
     print(" Inside:") 
     self.info() 
     print("<- ImportSqlTableModel.__init__:") 


    def info(self): 
     print("-> info") 

     print(" ImportSqlTableModel tables inside :", self.database().tables()) 
     print(" ImportSqlTableModel self.db  :", self.database()) 
     print(" ImportSqlTableModel self.Table :", self.tableName()) 
     print(" ImportSqlTableModel self.rowCount :", self.rowCount()) 
     print(" ImportSqlTableModel self.lastEror :", self.lastError().text()) 
     print("<- info") 
    def columnCount(self, index): 
     count = QSqlTableModel.columnCount(self, index) 
     return count 

    def dataChanged(self, QModelIndex, QModelIndex_1, Iterable, p_int=None, *args, **kwargs): 
     print("-> Datachanged") 

    def data(self, index, role=Qt.DisplayRole): 
     print("-> ImportSqlModel.data",index, role) 
     print(" 1row :", index.row()) 
     print(" col :", index.column()) 
     print(" data :", self.record().fieldName(index.column())) 
     value = super(ImportSqlTableModel, self).data(index) 
     print(" value2:",value) 

     if index.column() in self.booleanSet: 
      if role == Qt.CheckStateRole: 
       if value == 2: 
        return QVariant(Qt.Unchecked) 
       else: 
        return QVariant(Qt.Checked) 
      else: 
       QSqlTableModel.data(self, index, role) 
     else: 
      return QSqlTableModel.data(self, index, role) 

    def setData(self, index, value, role=Qt.EditRole): 
     # works with changing value, but not saving 
     print("-> ImportSqlModel.setData",index,value,role) 
     print(" value:", value) 
     if not index.isValid(): 
      return False 
     if role == Qt.EditRole: 
      print(" = Qt.Editrole") 
      QVariant(value) 
      print(" Update table") 
      self.select() 
     if index.column() in self.booleanSet and role == Qt.CheckStateRole: 
      print(" checkbox changed!") 
      if value == Qt.Checked: 
       print(" Qt.Checked") 
       return QSqlTableModel.setData(self, index, 2 , Qt.EditRole) 
      else: 
       print(" not Qt.Checked") 
       return QSqlTableModel.setData(self, index, 0 , Qt.EditRole) 
     else: 
      return QSqlTableModel.setData(self, index, value, role) 

    def flags(self, index): 
     print("-> ImportSqlModel.flags") 
     print(" index.isValid()",index.isValid()) 
     if not index.isValid(): 
      return Qt.ItemIsEnabled 
     if index.column() in self.booleanSet: 
      return Qt.ItemIsUserCheckable | Qt.ItemIsEnabled # | Qt.ItemIsSelectable | Qt.ItemIsEditable 
     elif index.column() in self.readOnlySet: 
      return Qt.ItemIsSelectable | Qt.ItemIsEnabled 
     else: 
      return QSqlTableModel.flags(self, index) 
     print("<- ImportSqlModel.flags") 


####################################################################################################################### 
#            D E M O F U N C T I O N 
####################################################################################################################### 

def createConnection(): 
    db = QSqlDatabase.addDatabase('QSQLITE') 
    db.setDatabaseName('memory') 
    if not db.open(): 
     QMessageBox.critical(None, qApp.tr("Cannot open database"), 
          qApp.tr("Unable to establish a database connection.\n" 
            "This example needs SQLite support. Please read " 
            "the Qt SQL driver documentation for information " 
            "how to build it.\n\n" 
            "Click Cancel to exit."), 
          QMessageBox.Cancel) 
     return False 

    query = QSqlQuery() 
    query.exec_("CREATE TABLE `typeOfValue` (`ID` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, "\ 
    "`name` TEXT NOT NULL, `unit` TEXT NOT NULL,`source` TEXT,`import` INTEGER,`importIfZero` INTEGER,"\ 
    "`visible` INTEGER);") 

    query.exec_('insert into typeOfValue (name, unit, source, import, importIfZero, visible) values '\ 
       '("Sound", "dB", "live", 0,0,2)') 
    query.exec_('insert into typeOfValue (name, unit, source, import, importIfZero, visible) values '\ 
       '("Flow", "m/min", "live", 0,2,2)') 
    query.exec_('insert into typeOfValue (name, unit, source, import, importIfZero, visible) values '\ 
       '("Vibration", "mm/s", "live", 2,2,2)') 
    query.exec_('insert into typeOfValue (name, unit, source, import, importIfZero, visible) values '\ 
       '("Voltage", "V", "live", 0,0,0)') 
    query.exec_('insert into typeOfValue (name, unit, source, import, importIfZero, visible) values '\ 
       '("Ampere", "A", "live", 2,0,2)') 
    return db 
####################################################################################################################### 
#            M A I N 
####################################################################################################################### 

if __name__ == '__main__': 
    createConnection() 
    app = QApplication(sys.argv) 
    prog = ImportFilter() 
    prog.show() 
    sys.exit(app.exec_()) 

내가에서 실행중인 문제, 내가 그것을 채우기 위해 쿼리를 사용할 때 테이블을 볼 수 있어요 것입니다 , 이는 읽기 전용 테이블로 이어진다. 이 수행되어서는 안된다는 매뉴얼에 설명되어 있습니다 : 참조 here 그래서 나는 = TABLENAME

 self.tableView_typeOfValues_Model = ImportSqlTableModel(self.gVar.db) 
     self.tableView_typeOfValues_Model.setTable("typeOfValue") 
    self.tableView_typeOfValues_Model.setEditStrategy(QSqlTableModel.OnFieldChange) 

     self.tableView_typeOfValues_Model.select() 

.setTable("typeOfValue") #으로 변경하지만 지금은 비어있는보기가 나는 self.lastError().text()를 호출하면 나는 테이블이 그 메시지를 받았습니다 self.database().tables() (모델 내부라고도 함)이 빈 목록을 가져 오기 때문에 찾을 수 없습니다. 즉, 데이터베이스가 올바르게 초기화되지 않았지만 self.database()은 결과적으로 PyQt5.QtSql.QSqlDatabase 객체를 0x042C4D30에 가져옵니다.

누군가 QSqlTableModel의 서브 클래 싱을 수정하는 힌트를 제공 할 수 있습니까? 감사!

+0

왜 테이블에 열을 하나 더 추가합니까? – eyllanesc

+0

질문을 이해할 수 없습니다. 어쩌면 내가 명확하게 설명하지 않았을 수도 있습니다. 7 개의 열과 4,5,6 개의 열이 부울이며 0 또는 2로 채워집니다.이 예에서 한 오타가 있으면이를 바꿉니다. – Hans

+0

이 코드는 다음과 같습니다 :'def columnCount (self, index) : count = QSqlTableModel.columnCount (self, index) return count + 1'은 뷰에 새로운 컬럼이 있다고 말합니다. – eyllanesc

답변

0

문제가 불리언 타입의 열 활성화되지 않은 Qt.ItemIsEditable 플래그에 의해 발생되며,이 명령어에 필요한 :

if index.column() in self.booleanSet and role == Qt.CheckStateRole: 
    print(" checkbox changed!") 
    if value == Qt.Checked: 
     print(" Qt.Checked") 
     return QSqlTableModel.setData(self, index, 2 , Qt.EditRole) 
    else: 
     print(" not Qt.Checked") 
     return QSqlTableModel.setData(self, index, 0 , Qt.EditRole) 

를이 필드는 편집 할 수 있는지 확인하기 때문이다.

class ReadOnlyDelegate(QItemDelegate): 
    def createEditor(self, parent, option, index): 
     lb = QLabel(parent) 
     return lb 

전체 예 :

import sys 

from PyQt5.QtCore import QVariant, Qt 
from PyQt5.QtSql import QSqlTableModel, QSqlDatabase 
from PyQt5.QtWidgets import QApplication, QTableView, QLabel, QItemDelegate 


class ImportSqlTableModel(QSqlTableModel): 
    def __init__(self, *args, **kwargs): 
     super(ImportSqlTableModel, self).__init__(*args, **kwargs) 
     self.booleanSet = [4, 5, 6] # column with checkboxes 
     self.readOnlySet = [1] # columns which must not be changed 
     self.setTable("typeOfValue") 
     self.setEditStrategy(QSqlTableModel.OnFieldChange) 
     self.select() 

    def data(self, index, role=Qt.DisplayRole): 
     value = super(ImportSqlTableModel, self).data(index) 
     if index.column() in self.booleanSet: 
      if role == Qt.CheckStateRole: 
       return Qt.Unchecked if value == 2 else Qt.Checked 
      else: 
       return QVariant() 
     return QSqlTableModel.data(self, index, role) 

    def setData(self, index, value, role=Qt.EditRole): 
     if not index.isValid(): 
      return False 
     if index.column() in self.booleanSet: 
      if role == Qt.CheckStateRole: 
       val = 2 if value == Qt.Unchecked else 0 
       return QSqlTableModel.setData(self, index, val, Qt.EditRole) 
      else: 
       return False 
     else: 
      return QSqlTableModel.setData(self, index, value, role) 

    def flags(self, index): 
     if not index.isValid(): 
      return Qt.NoItemFlags 
     if index.column() in self.booleanSet: 
      return Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsEditable 
     elif index.column() in self.readOnlySet: 
      return Qt.ItemIsSelectable | Qt.ItemIsEnabled 
     else: 
      return QSqlTableModel.flags(self, index) 


class ReadOnlyDelegate(QItemDelegate): 
    def createEditor(self, parent, option, index): 
     lb = QLabel(parent) 
     return lb 


if __name__ == '__main__': 
    app = QApplication(sys.argv) 

    db = QSqlDatabase.addDatabase("QSQLITE") 
    db.setDatabaseName("/path/of/your_database.db") 
    if not db.open(): 
     sys.exit(-1) 
    model = ImportSqlTableModel() 
    w = QTableView() 
    w.setModel(model) 
    for col in model.booleanSet: 
     w.setItemDelegateForColumn(col, ReadOnlyDelegate(w)) 
    w.show() 
    sys.exit(app.exec_()) 
+0

고마워요. 나는 아직 내 잘못을 찾고 있는데, 데이터베이스 문제는 찾지 못했지만, 대의원은 내가 확실히 생각하지 못했던 것이다. – Hans

0

고장

그래서이 솔루션은 우리가 대리인을 통해 편집기를 사용할 수 없게됩니다 일부 텍스트를 쓸 수 있다는이 플래그를 가능하게하지만, 방지하는 것입니다 에 관한 다른 QSqlDatabase object의 호출에 서브 클래스 QSqlTableModel했다. 소스가 실제 db이면 assignedModel = YourSubclassedTableModel(db=your_open_database_object)이어야합니다. 데이터베이스가 메모리에있는 경우 db.setDatabaseName(':memory:')이 db는 기본 db이며 모델 내에서 사용됩니다. 문서에서는 언급하지 않습니다. Qt는 설명서에서 당신은 발견 할 것이다 : QSqlTableModel :: QSqlTableModel

(QObject를 * 부모 = Q_NULLPTR는 QSqlDatabase dB = QSqlDatabase()) 빈 QSqlTableModel를 작성하고 부모와 dB로 데이터베이스 연결에 부모를 설정합니다. db가 유효하지 않으면 기본 데이터베이스 연결이 사용됩니다.

+0

메모리는': memory :' – eyllanesc

+0

네가 맞아, 예제는':'없이도 작동했다. 나는 대답을 정정했다. – Hans

관련 문제