2017-12-30 35 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 は、だから私は.setTable("typeOfValue")#=テーブル名

 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() 

に変更しかし、今、私は空のビューを持っていると私はself.lastError().text()を呼び出す場合、私はテーブルというメッセージが表示されましたself.database().tables()(モデルの内側と呼ばれます)が空のリストを取得するため、検索されません。つまり、データベースは正しく初期化されていませんが、self.database()は結果として PyQt5.QtSql.QSqlDatabaseオブジェクトを0x042C4D30に変換します。

QSqlTableModelをサブクラス化するヒントを教えてください。ありがとう!問題は、ブール型の列が使用できないため、Qt.ItemIsEditableフラグによって引き起こされる

+0

なぜテーブルに列をもう1つ追加しますか? – eyllanesc

+0

私はあなたの質問を理解していません。たぶん私は明確に説明していないかもしれません。 7つの列があり、4,5,6列はブール値で、0または2で塗りつぶされます。この例では、1つのタイプミスが置き換えられます。 – Hans

+0

このコードは: 'def columnCount(self、index): count = QSqlTableModel.columnCount(self、index) return count + 1'は、新しい列があることを表示しています – eyllanesc

答えて

0

、この命令に必要である:

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の呼び出しにあった。ソースが物理データベースの場合はassignedModel = YourSubclassedTableModel(db=your_open_database_object)にする必要があります。データベースがメモリ内にある場合db.setDatabaseName(':memory:')このdbはデフォルトのdbであり、モデル内で使用されます。ドキュメントには言及していません。あなたは見つけるでしょうQtのマニュアルで:

QSqlTableModel :: QSqlTableModel(QObjectを*親= Q_NULLPTR、QSqlDatabaseデシベル= QSqlDatabase()) は空QSqlTableModelを作成し、親の親とDBへのデータベース接続を設定します。 dbが有効でない場合、デフォルトのデータベース接続が使用されます。

+0

メモリは ':memory:' – eyllanesc

+0

ですが、この例は ':'なしでも動作しています。私は答えを訂正しました。 – Hans

関連する問題