Форум сайта python.su
Использую PyQt
Делается связка DB -> model -> QTableView
model - перегружаю класс QSqlQueryModel.
В методе flags выставляю флаги flags |=ItemIsUserCheckable, чтоб появился чекбокс в ячейке.
В методе data для DisplayRole возвращаю None, чтоб видеть только чекбокс во 2-м столбце и не видеть данные.
Чекбокс при нажатии на него не меняет своего состояния.
Как сделать, чтоб чекбокс менял состояние при нажатии на него?
Аналогичный код в QtCreator на С++ работает
editablesqlmodel.py
from PyQt5 import QtCore, QtGui, QtWidgets, QtSql class EditableSqlModel(QtSql.QSqlQueryModel): def __init__(self): super().__init__() def flags(self, index): flags = super(EditableSqlModel, self).flags(index) if index.column() in (0,1): flags |= QtCore.Qt.ItemIsEditable elif (index.column() == 2): #flags |= QtCore.Qt.ItemIsUserCheckable flags |= QtCore.Qt.ItemIsUserCheckable return flags def data(self,index, role=QtCore.Qt.DisplayRole): if not index.isValid(): return None data=super(EditableSqlModel,self).data(index,role) if index.column()==2: if role != QtCore.Qt.DisplayRole: data1=super(EditableSqlModel,self).data(index,QtCore.Qt.DisplayRole) val = QtCore.Qt.Checked if data1 else QtCore.Qt.Unchecked return val else: return None else: return data
import sys from PyQt5.QtWidgets import QApplication, QAction, QWidget from PyQt5 import QtCore, QtGui, QtWidgets, QtSql from PyQt5 import QtGui, QtCore from editablesqlmodel import EditableSqlModel import connection from PyQt5.uic import loadUi class excelSort(QtCore.QSortFilterProxyModel): def setValues(self,mdl): print ("start setval") print(mdl.columnCount()) self.dflt=[{}] print ("кол-во колонок %d" % mdl.columnCount()) print ("кол-во строк %d" % mdl.rowCount()) for i in range(mdl.columnCount()): self.dflt.insert(i,{}) # словарь с признаком сортировки for j in range(mdl.rowCount()): #print(mdl.data(mdl.index(j,i),QtCore.Qt.DisplayRole)) self.dflt[i][mdl.data(mdl.index(j,i),QtCore.Qt.DisplayRole)]=False #self.dflt[1].pop("33UVB05EJ003") print(self.dflt[1],"dflt[1]") print ("exit setval") def filterAcceptsRow (self, source_row, source_parent): #one of our children might be accepted, so accept this row if one of our children are accepted. source_index = self.sourceModel().index(source_row, 0, source_parent) #col = source_index.column() row = source_index.row() #print("row ",row) for i in range( self.sourceModel().columnCount()): #print(self.sourceModel().data(self.sourceModel().index(row,i),QtCore.Qt.DisplayRole)) if self.sourceModel().data(self.sourceModel().index(row,i),QtCore.Qt.DisplayRole) in self.dflt[i]: return True #print("exit_filter") return False class mw(QWidget): def __init__(self): super().__init__() self.wd=loadUi('mainwindow.ui') self.wd.show() def algs(self): print("start algs") self.model=EditableSqlModel() tpl=(("кодAlg","кодAlg","кодAlg"), ("alg","alg","alg"), ("кодalg","name","addv")) try: self.model.setPK(tpl) except Exception as err: print(err) try: self.model.setQuery('SELECT КодAlg,NAME,AddV FROM Alg',self.db) if self.model.lastError().isValid(): print(self.model.lastError().text()) self.model.setHeaderData(1, QtCore.Qt.Horizontal, "Алгоритм") self.model.setHeaderData(2, QtCore.Qt.Horizontal, "Пометка") self.model.query() #self.wd.tableView.setModel(self.model) #self.flt=QtCore.QSortFilterProxyModel() self.flt=excelSort() self.flt.setSourceModel(self.model) self.flt.setValues(self.model) self.wd.tableView.setModel(self.flt) self.wd.tableView.setSortingEnabled(True) #print(self.model.record(1).value(1)) self.wd.tableView.show() except Exception as err: print(err) return True def createMenus(self): msgAction = QAction("Алгоритмы",self.wd.menuBar) msgAction.triggered.connect(self.algs) self.wd.menuBar.addAction(msgAction) def main(args): app=QApplication(sys.argv) mw1=mw() mw1.createMenus() db_file = r'''D:\Zone_4block_prog_06_11_17.accdb''' mw1.db=connection.createConnection(db_file) if not mw1.db: sys.exit(1) sys.exit(app.exec_()) if __name__ == '__main__': main(sys.argv)
import pyodbc from PyQt5.QtSql import QSqlQueryModel,QSqlDatabase,QSqlQuery def createConnection(db_file): try: user = '' password = '' odbc_conn_str = 'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=%s;' %\ (db_file) db = QSqlDatabase.addDatabase("QODBC") db.setDatabaseName("DRIVER=Microsoft Access Driver (*.mdb, *.accdb);FIL=MS Access;DBQ=d:\\QtPrj\\Zone_db\\Zone_test.accdb") #----------------------- if not db.open(): print("Can't open database") return None #conn = pyodbc.connect(odbc_conn_str) return db except Exception as err: print(err) return None
Офлайн
man1985В этом методе сделай вывод всех ветвей в консоль через print(). Скорее всего, ты не знаешь про многие срабатывания, которые включают флажок обратно.def data(self,index, role=QtCore.Qt.DisplayRole): if not index.isValid(): return None data=super(EditableSqlModel,self).data(index,role) if index.column()==2: if role != QtCore.Qt.DisplayRole: data1=super(EditableSqlModel,self).data(index,QtCore.Qt.DisplayRole) val = QtCore.Qt.Checked if data1 else QtCore.Qt.Unchecked return val else: return None else: return data
Офлайн
data1=super(EditableSqlModel,self).data(index,QtCore.Qt.DisplayRole)
Офлайн
py.user.next
В этом методе сделай вывод всех ветвей в консоль через print()
def data(self,index, role=QtCore.Qt.DisplayRole): print("-------------method data--------role=",role) if not index.isValid(): return None data=super(EditableSqlModel,self).data(index,role) if index.column()==2: if role != QtCore.Qt.DisplayRole: data1=super(EditableSqlModel,self).data(index,QtCore.Qt.CheckStateRole) val = QtCore.Qt.Checked if data1 else QtCore.Qt.Unchecked print(" Value val=%d index.row=%d index.col=%d " % (val,index.row(),index.column())) return val else: print(" return None index.row=%d index.col=%d " % (index.row(),index.column())) return None else: print(" return Data index.row=%d index.col=%d " % (index.row(),index.column())) return data
-------------method data--------role= 10 Value val=0 index.row=115 index.col=2 -------------method data--------role= 6 Value val=0 index.row=115 index.col=2 -------------method data--------role= 7 Value val=0 index.row=115 index.col=2 -------------method data--------role= 9 Value val=0 index.row=115 index.col=2 -------------method data--------role= 10 Value val=0 index.row=115 index.col=2 -------------method data--------role= 1 Value val=0 index.row=115 index.col=2 -------------method data--------role= 0 return None index.row=115 index.col=2 -------------method data--------role= 8 Value val=0 index.row=115 index.col=2 -------------method data--------role= 6 Value val=0 index.row=115 index.col=2 -------------method data--------role= 7 Value val=0 index.row=115 index.col=2 -------------method data--------role= 9 Value val=0 index.row=115 index.col=2 -------------method data--------role= 10 Value val=0 index.row=115 index.col=2 -------------method data--------role= 1 Value val=0 index.row=115 index.col=2 -------------method data--------role= 0 return None index.row=115 index.col=2 -------------method data--------role= 8 Value val=0 index.row=115 index.col=2 -------------method data--------role= 10 Value val=0 index.row=115 index.col=2 -------------method data--------role= 6 Value val=0 index.row=115 index.col=2 -------------method data--------role= 7 Value val=0 index.row=115 index.col=2 -------------method data--------role= 9 Value val=0 index.row=115 index.col=2 -------------method data--------role= 10 Value val=0 index.row=115 index.col=2 -------------method data--------role= 1 Value val=0 index.row=115 index.col=2 -------------method data--------role= 0 return None index.row=115 index.col=2 -------------method data--------role= 8 Value val=0 index.row=115 index.col=2 -------------method data--------role= 0 return Data index.row=115 index.col=0 -------------method data--------role= 6 Value val=0 index.row=115 index.col=2 -------------method data--------role= 7 Value val=0 index.row=115 index.col=2 -------------method data--------role= 9 Value val=0 index.row=115 index.col=2 -------------method data--------role= 10 Value val=0 index.row=115 index.col=2 -------------method data--------role= 1 Value val=0 index.row=115 index.col=2 -------------method data--------role= 0 return None index.row=115 index.col=2 -------------method data--------role= 8 Value val=0 index.row=115 index.col=2
Офлайн
RodegastНе помогло
QtCore.Qt.CheckStateRole
Офлайн
> Не помогло
А чего ты хотел? QSqlQueryModel просто отображает данные, для того что бы их редактировать тебе нужно:
1) Переопределить метод setData у модели так что бы в в нём происходила запись в БД.
2) Создать делегату и повесить её на соответствующий столбец
3) В делегате вызывать редактор, когда редактор закрыт, вызывать из делегаты метод модели setData и передавать туду дынные для изменения.
Офлайн
RodegastПереопределил метод setData,запись в БД -происходит
А чего ты хотел? QSqlQueryModel просто отображает данные, для того что бы их редактировать тебе нужно:
1) Переопределить метод setData у модели так что бы в в нём происходила запись в БД.
2) Создать делегату и повесить её на соответствующий столбец
3) В делегате вызывать редактор, когда редактор закрыт, вызывать из делегаты метод модели setData и передавать туду дынные для изменения.
Query to ex: SELECT КодAlg,NAME,AddV FROM Alg [Microsoft][Диспетчер драйверов ODBC] Ошибка последовательности функций QODBC3: Unable to execute statement
def setData(self, index, value, role): if not index.isValid(): return None ok=False print("start SetData") row=index.row() col = index.column() primaryKeyIndex = self.index(row, self.pktn['keyIdx'][col]) id1 = super(EditableSqlModel, self).data(primaryKeyIndex) query=QtSql.QSqlQuery() str1="update " + self.pktn['table'][col] + " set " + self.pktn['valName'][col] + \ " = '" + str(value) + "' where " + self.pktn['keyName'][col] + " = " + \ str(id1) query.prepare(str1) ok = query.exec_() if not ok: print(query().lastError().text()) return False self.dataChanged.emit(index,index) #self.dataChanged(index,index) str1=self.query().executedQuery() print("Query to ex:",str1) self.setQuery(str1) ok=self.query().exec_() if not ok: print(self.query().lastError().text()) return False return ok
Офлайн
> Делегата не нужна для редактирования, при нажатии на чекбокс в setData передаются данные соответствующие инвертированному состоянию чекбокса
Обычно её всё равно определяют.
> Как заставить отработать dataChanged.emit(index,index)?
Этот сигнал нужен только для того что бы виджет смог при необходимости узнать что данные могли поменяться. Что бы про это узнала модель нужно вызывать что то вроде beginResetModel / endResetModel
Отредактировано Rodegast (Авг. 17, 2018 02:12:07)
Офлайн
RodegastbeginResetModel / endResetModel - не помогло
Этот сигнал нужен только для того что бы виджет смог при необходимости узнать что данные могли поменяться. Что бы про это узнала модель нужно вызывать что то вроде beginResetModel / endResetModel
str1=self.query().executedQuery() self.setQuery(str1)
ok=self.query().exec_() if not ok: print(self.query().lastError().text()) return False return ok
Офлайн