tgr*_*dje 6 python pyqt qtableview python-2.7 pandas
我对 python 和使用都很陌生WinPython-32bit-2.7.10.3(包括QTDesigner 4.8.7。我正在尝试使用 QtableViews 编写一个接口,以便在两个独立的项目上使用 sqlite 数据库。
该算法大致如下:
\n- 连接到数据库并将数据转换为pandas.DataFrame
\n- 将 DataFrame 转换为 QAbstractTableModel
\n- 将 QAbstractTableModel 应用到tableview.model
\n- 加载对话框
我没有得到相同的行为,具体取决于用于创建数据帧的 sql:\n给定一个 SQL 表“参数”,具有 3 个字段(LIBELLE 作为 varchar,VALEUR 作为 varchar,TEST 作为布尔值),尝试的 sql 是:
\n\n通过第一个请求,我可以编辑表格视图内的数据。对于第二个请求,我可以选择一个“单元格”,对其进行编辑,但是当我提交版本(按 Enter 键)时,数据将设置回其第一个值。
\n\n在搜索时,我发现无论“任何”值是什么,setData 代码的这一行都不起作用:
\n\nself._data.values[index.row()][index.column()] = "anything"\nRun Code Online (Sandbox Code Playgroud)\n\n您可以通过删除主代码中第27行开头的#字符来测试sql源的发生率。
\n\n我已将代码截断到严格的最低限度(非常接近我的第一个项目的原始工作代码),并且我感到非常困惑。如果有人有想法,那就太好了!
\n\n谢谢
\n\nPS:我后来发布了代码,但我还没有找到加入的方法sqlite.db...如果有人可以指导我,我会很高兴添加它;与此同时,我已经在我的google.drive上加入了该地段的整个 zip
编辑#2:
\n\n仍然无法理解那里出了什么问题,但我刚刚发现一旦加载数据就无法将数据提交到模型。我很确定这是我问题的核心,并随后更新了问题和标题。
\n\n主要代码:
\n\n#\xc2\xad*\xc2\xadcoding: utf\xc2\xad8 \xc2\xad*\xc2\xad\n\nfrom PyQt4 import QtCore, QtGui\n\nimport os,sys\nfrom parametrage import Ui_WinParam\nfrom PANDAS_TO_PYQT import PandasModel\n\nimport pandas as pd\nimport sqlite3\n\nclass window_parametreur(QtGui.QDialog, Ui_WinParam):\n def __init__(self, dataframemodel, parent=None): \n QtGui.QDialog.__init__(self, parent)\n # Set up the user interface from Designer.\n self.ui = Ui_WinParam()\n self.ui.setupUi(self)\n self.setModal(True) \n self.ui.tableView.setModel(dataframemodel)\n self.ui.tableView.resizeColumnsToContents()\n\ndef OpenParametreur(self, db_path):\n\n #connecting to database and getting datas as pandas.dataframe\n con = sqlite3.connect(db_path)\n strSQL = u\'SELECT LIBELLE AS "Param\xc3\xa8tre", VALEUR AS "Valeur" FROM parametres\'.encode("utf-8")\n #strSQL = u\'SELECT * FROM parametres\'.encode("utf-8")\n data = pd.read_sql_query(strSQL, con)\n con.close()\n\n #converting to QtCore.QAbstractTableModel\n model = PandasModel(data)\n\n #loading dialog\n self.f=window_parametreur(model) \n self.f.exec_()\n\nif __name__=="__main__":\n a=QtGui.QApplication(sys.argv)\n f=QtGui.QMainWindow()\n print OpenParametreur(f, ".\\SQLiteDataBase.db")\nRun Code Online (Sandbox Code Playgroud)\n\n“PANDAS_TO_PYQT.py”的代码,被调用以将 pandas.dataframe 转换为 QtCore.QAbstractTableModel
\n\n#\xc2\xad*\xc2\xadcoding: utf\xc2\xad8 \xc2\xad*\xc2\xad\n\nfrom PyQt4 import QtCore, QtGui\n\nclass PandasModel(QtCore.QAbstractTableModel):\n def __init__(self, data, parent=None):\n QtCore.QAbstractTableModel.__init__(self, parent)\n self._data = data\n\n def rowCount(self, parent=None):\n return len(self._data.values)\n\n def columnCount(self, parent=None):\n return self._data.columns.size\n\n def data(self, index, role=QtCore.Qt.DisplayRole):\n if index.isValid():\n if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:\n return QtCore.QVariant(unicode(\n self._data.values[index.row()][index.column()]))\n return QtCore.QVariant()\n\n def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):\n if role != QtCore.Qt.DisplayRole:\n return None\n if orientation == QtCore.Qt.Horizontal:\n try:\n return \'%s\' % unicode(self._data.columns.tolist()[section], encoding="utf-8")\n except (IndexError, ):\n return QtCore.QVariant()\n elif orientation == QtCore.Qt.Vertical:\n try:\n return \'%s\' % self._data.index.tolist()[section]\n except (IndexError, ):\n return QtCore.QVariant()\n\n def flags(self, index):\n return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable\n\n def setData(self, index, value, role=QtCore.Qt.EditRole):\n if index.isValid():\n\n print "data set with keyboard : " + value.toByteArray().data().decode("latin1")\n self._data.values[index.row()][index.column()] = "anything"\n print "data committed : " +self._data.values[index.row()][index.column()]\n\n self.dataChanged.emit(index, index)\n return True\n return QtCore.QVariant()\nRun Code Online (Sandbox Code Playgroud)\n\nparametrage.py 的代码,由 QtDesigner 创建,包含对话框源:
\n\n# -*- coding: utf-8 -*-\n\n# Form implementation generated from reading ui file \'parametrage.ui\'\n#\n# Created by: PyQt4 UI code generator 4.11.4\n#\n# WARNING! All changes made in this file will be lost!\n\nfrom PyQt4 import QtCore, QtGui\n\ntry:\n _fromUtf8 = QtCore.QString.fromUtf8\nexcept AttributeError:\n def _fromUtf8(s):\n return s\n\ntry:\n _encoding = QtGui.QApplication.UnicodeUTF8\n def _translate(context, text, disambig):\n return QtGui.QApplication.translate(context, text, disambig, _encoding)\nexcept AttributeError:\n def _translate(context, text, disambig):\n return QtGui.QApplication.translate(context, text, disambig)\n\nclass Ui_WinParam(object):\n def setupUi(self, WinParam):\n WinParam.setObjectName(_fromUtf8("WinParam"))\n WinParam.resize(608, 279)\n icon = QtGui.QIcon()\n icon.addPixmap(QtGui.QPixmap(_fromUtf8("../../pictures/EAUX.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)\n WinParam.setWindowIcon(icon)\n self.gridLayout = QtGui.QGridLayout(WinParam)\n self.gridLayout.setObjectName(_fromUtf8("gridLayout"))\n self.ButtonBox = QtGui.QDialogButtonBox(WinParam)\n self.ButtonBox.setOrientation(QtCore.Qt.Horizontal)\n self.ButtonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)\n self.ButtonBox.setCenterButtons(True)\n self.ButtonBox.setObjectName(_fromUtf8("ButtonBox"))\n self.gridLayout.addWidget(self.ButtonBox, 1, 0, 1, 1)\n self.tableView = QtGui.QTableView(WinParam)\n self.tableView.setEditTriggers(QtGui.QAbstractItemView.DoubleClicked)\n self.tableView.setSortingEnabled(False)\n self.tableView.setObjectName(_fromUtf8("tableView"))\n self.gridLayout.addWidget(self.tableView, 0, 0, 1, 1)\n\n self.retranslateUi(WinParam)\n QtCore.QObject.connect(self.ButtonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), WinParam.accept)\n QtCore.QObject.connect(self.ButtonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), WinParam.reject)\n QtCore.QMetaObject.connectSlotsByName(WinParam)\n\n def retranslateUi(self, WinParam):\n WinParam.setWindowTitle(_translate("WinParam", "Param\xc3\xa9trage", None))\n\n\nif __name__ == "__main__":\n import sys\n app = QtGui.QApplication(sys.argv)\n WinParam = QtGui.QDialog()\n ui = Ui_WinParam()\n ui.setupUi(WinParam)\n WinParam.show()\n sys.exit(app.exec_())\nRun Code Online (Sandbox Code Playgroud)\n
我终于想通了...但我仍然不知道为什么 pandas 仅通过更改 SQL 请求就可以不同地工作(必须是 read_sql_query 过程中的某些内容...)
\n\n为了让课程正常工作,我必须更改“PANDAS_TO_PYQT.py”的代码,替换
\n\nself._data.values[index.row()][index.column()]\nRun Code Online (Sandbox Code Playgroud)\n\n经过
\n\nself._data.iloc[index.row(),index.column()]\nRun Code Online (Sandbox Code Playgroud)\n\n在 setData 和 data 函数中。
\n\n不知何故,pandas 似乎在这个过程中生成了数据帧的副本(对于那些寻找解释的人,请转到doc)。
\n\n因此,将数据帧转换为 QAbstractTableModel 的正确类代码是:
\n\n#\xc2\xad*\xc2\xadcoding: utf\xc2\xad8 \xc2\xad*\xc2\xad\n\nfrom PyQt4 import QtCore, QtGui\n\nclass PandasModel(QtCore.QAbstractTableModel):\n def __init__(self, data, parent=None):\n QtCore.QAbstractTableModel.__init__(self, parent)\n self._data = data\n\n def rowCount(self, parent=None):\n return len(self._data.values)\n\n def columnCount(self, parent=None):\n return self._data.columns.size\n\n def data(self, index, role=QtCore.Qt.DisplayRole):\n if index.isValid():\n if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:\n return QtCore.QVariant(unicode(\n self._data.iloc[index.row(),index.column()]))\n return QtCore.QVariant()\n\n def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):\n if role != QtCore.Qt.DisplayRole:\n return None\n if orientation == QtCore.Qt.Horizontal:\n try:\n return \'%s\' % unicode(self._data.columns.tolist()[section], encoding="utf-8")\n except (IndexError, ):\n return QtCore.QVariant()\n elif orientation == QtCore.Qt.Vertical:\n try:\n return \'%s\' % self._data.index.tolist()[section]\n except (IndexError, ):\n return QtCore.QVariant()\n\n def flags(self, index):\n return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable\n\n def setData(self, index, value, role=QtCore.Qt.EditRole):\n if index.isValid():\n self._data.iloc[index.row(),index.column()] = value.toByteArray().data().decode("latin1")\n if self.data(index,QtCore.Qt.DisplayRole) == value.toByteArray().data().decode("latin1"):\n self.dataChanged.emit(index, index)\n return True\n return QtCore.QVariant()\nRun Code Online (Sandbox Code Playgroud)\n