Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用PyQt5反转QTableView中的列和行_Python_Sqlite_Pyqt - Fatal编程技术网

Python 使用PyQt5反转QTableView中的列和行

Python 使用PyQt5反转QTableView中的列和行,python,sqlite,pyqt,Python,Sqlite,Pyqt,对于PyQT5小部件,我需要显示从SQL查询到SQLite数据库的数据,并反转/旋转列和行。理想情况下,在QTableView中。(此表只有2列,一列用于前面的列名,另一列用于它们的值。此表用于显示将在SQL查询中聚合的统计信息,该查询将只返回一行。因此,我希望从一行多列转到两列多行。) 我想出了一个变通办法,用QFormLayout做正确的事情,但是它看起来很难看,看起来很不雅观。(请参阅显示数据(自)方法。) 使用QTableView实现这一点的正确方法是什么?使用QTableView的正确

对于PyQT5小部件,我需要显示从SQL查询到SQLite数据库的数据,并反转/旋转列和行。理想情况下,在QTableView中。(此表只有2列,一列用于前面的列名,另一列用于它们的值。此表用于显示将在SQL查询中聚合的统计信息,该查询将只返回一行。因此,我希望从一行多列转到两列多行。)

我想出了一个变通办法,用QFormLayout做正确的事情,但是它看起来很难看,看起来很不雅观。(请参阅
显示数据(自)
方法。)


使用QTableView实现这一点的正确方法是什么?

使用
QTableView
的正确方法是使用
QTableModel

幸运的是,有一种方法允许您根据SQL表构建表模型。 回答了一个类似的问题,指出可以通过重新定义
mapToSource
mapFromSource
方法来“在此基础上”更改数据模型的表示形式

还有一些方法可以直接从SQL命令转换SQL请求的结果。看

也值得一读:。这是C++版本,但是PyQt遵循相同的原则(并且类具有相同的名称)。
希望有帮助。

使用
QTableView
的正确方法是使用
QTableModel

幸运的是,有一种方法允许您根据SQL表构建表模型。 回答了一个类似的问题,指出可以通过重新定义
mapToSource
mapFromSource
方法来“在此基础上”更改数据模型的表示形式

还有一些方法可以直接从SQL命令转换SQL请求的结果。看

也值得一读:。这是C++版本,但是PyQt遵循相同的原则(并且类具有相同的名称)。
希望这能有所帮助。

在进一步搜索和阅读@PlikPlok留下的有用指针后,我找到了一个解决方案:

显然,此功能不是由任何现成的Qt类提供的,因此您必须同时为QabStretcProxyModel和QSqlRelationalDelegate子类,然后在表中使用它们:

#!/usr/bin/python3

import sys
from PyQt5 import QtSql
from PyQt5.QtWidgets import (QWidget, QApplication,
                             QGridLayout, QTableView)
from PyQt5.Qt import (QModelIndex, QAbstractProxyModel, QSqlRelationalDelegate)
from PyQt5.QtCore import Qt

class FlippedProxyModel(QAbstractProxyModel):
    def __init__(self, parent=None):
        super().__init__(parent)

    def mapFromSource(self, index):
        return self.createIndex(index.column(), index.row())

    def mapToSource(self, index):
        return self.sourceModel().index(index.column(), index.row(), QModelIndex())

    def columnCount(self, parent):
        return self.sourceModel().rowCount(QModelIndex())

    def rowCount(self, parent):
        return self.sourceModel().columnCount(QModelIndex())

    def index(self, row, column, parent):
        return self.createIndex(row, column)

    def parent(self, index):
        return QModelIndex()

    def data(self, index, role):
        return self.sourceModel().data(self.mapToSource(index), role)

    def headerData(self, section, orientation, role):
        if orientation == Qt.Horizontal:
            return self.sourceModel().headerData(section, Qt.Vertical, role)
        if orientation == Qt.Vertical:
            return self.sourceModel().headerData(section, Qt.Horizontal, role)


class FlippedProxyDelegate(QSqlRelationalDelegate):
    def createEditor(self, parent, option, index):
        proxy = index.model()
        base_index = proxy.mapToSource(index)
        return super().createEditor(parent, option, base_index)

    def setEditorData(self, editor, index):
        proxy = index.model()
        base_index = proxy.mapToSource(index)
        return super().setEditorData(editor, base_index)

    def setModelData(self, editor, model, index):
        base_model = model.sourceModel()
        base_index = model.mapToSource(index)
        return super().setModelData(editor, base_model, base_index)


class InvertedTable(QWidget):
    def __init__(self, company):
        super().__init__()
        self.db_file = "test.db"
        self.company = company
        self.create_connection()
        self.fill_table()
        self.create_model()
        self.init_UI()

    def create_connection(self):
        self.db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
        self.db.setDatabaseName(self.db_file)
        if not self.db.open():
            print("Cannot establish a database connection to {}!".format(self.db_file))
            return False

    def fill_table(self):
        self.db.transaction()
        q = QtSql.QSqlQuery()
        q.exec_("DROP TABLE IF EXISTS Cars;")
        q.exec_("""CREATE TABLE Cars (Company TEXT, Model TEXT, Cars TEXT)""") 
        q.exec_("INSERT INTO Cars VALUES ('Honda', 'Civic', 5)") 
        q.exec_("INSERT INTO Cars VALUES ('Volkswagen', 'Golf', 3)")
        self.db.commit()

    def create_model(self):
        self.model = QtSql.QSqlTableModel()
        q = QtSql.QSqlQuery()
        query = """SELECT * from cars where company = 'Honda'
         """
        q.exec_(query)
        self.model.setQuery(q)
        self.proxy = FlippedProxyModel() # use flipped proxy model
        self.proxy.setSourceModel(self.model)

    def init_UI(self):
        self.grid = QGridLayout()
        self.setLayout(self.grid)
        self.table = QTableView()
        self.table.setModel(self.proxy)
        self.table.setItemDelegate(FlippedProxyDelegate(self.table)) # use flipped proxy delegate
        self.table.horizontalHeader().hide()

        self.grid.addWidget(self.table, 0, 0)

    def closeEvent(self, e):
        if (self.db.open()):
            self.db.close()

    def check_error(self, q):
        lasterr = q.lastError()
        if lasterr.isValid():
            print(lasterr.text())
            self.db.close()
            exit(1)


def main():
    app = QApplication(sys.argv)
    ex = InvertedTable("Honda")
    ex.show()

    result = app.exec_()
    sys.exit(result)


if __name__ == '__main__':
    main()      

在进一步搜索和阅读@PlikPlok留下的有用指针之后,我找到了一个解决方案:

显然,此功能不是由任何现成的Qt类提供的,因此您必须同时为QabStretcProxyModel和QSqlRelationalDelegate子类,然后在表中使用它们:

#!/usr/bin/python3

import sys
from PyQt5 import QtSql
from PyQt5.QtWidgets import (QWidget, QApplication,
                             QGridLayout, QTableView)
from PyQt5.Qt import (QModelIndex, QAbstractProxyModel, QSqlRelationalDelegate)
from PyQt5.QtCore import Qt

class FlippedProxyModel(QAbstractProxyModel):
    def __init__(self, parent=None):
        super().__init__(parent)

    def mapFromSource(self, index):
        return self.createIndex(index.column(), index.row())

    def mapToSource(self, index):
        return self.sourceModel().index(index.column(), index.row(), QModelIndex())

    def columnCount(self, parent):
        return self.sourceModel().rowCount(QModelIndex())

    def rowCount(self, parent):
        return self.sourceModel().columnCount(QModelIndex())

    def index(self, row, column, parent):
        return self.createIndex(row, column)

    def parent(self, index):
        return QModelIndex()

    def data(self, index, role):
        return self.sourceModel().data(self.mapToSource(index), role)

    def headerData(self, section, orientation, role):
        if orientation == Qt.Horizontal:
            return self.sourceModel().headerData(section, Qt.Vertical, role)
        if orientation == Qt.Vertical:
            return self.sourceModel().headerData(section, Qt.Horizontal, role)


class FlippedProxyDelegate(QSqlRelationalDelegate):
    def createEditor(self, parent, option, index):
        proxy = index.model()
        base_index = proxy.mapToSource(index)
        return super().createEditor(parent, option, base_index)

    def setEditorData(self, editor, index):
        proxy = index.model()
        base_index = proxy.mapToSource(index)
        return super().setEditorData(editor, base_index)

    def setModelData(self, editor, model, index):
        base_model = model.sourceModel()
        base_index = model.mapToSource(index)
        return super().setModelData(editor, base_model, base_index)


class InvertedTable(QWidget):
    def __init__(self, company):
        super().__init__()
        self.db_file = "test.db"
        self.company = company
        self.create_connection()
        self.fill_table()
        self.create_model()
        self.init_UI()

    def create_connection(self):
        self.db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
        self.db.setDatabaseName(self.db_file)
        if not self.db.open():
            print("Cannot establish a database connection to {}!".format(self.db_file))
            return False

    def fill_table(self):
        self.db.transaction()
        q = QtSql.QSqlQuery()
        q.exec_("DROP TABLE IF EXISTS Cars;")
        q.exec_("""CREATE TABLE Cars (Company TEXT, Model TEXT, Cars TEXT)""") 
        q.exec_("INSERT INTO Cars VALUES ('Honda', 'Civic', 5)") 
        q.exec_("INSERT INTO Cars VALUES ('Volkswagen', 'Golf', 3)")
        self.db.commit()

    def create_model(self):
        self.model = QtSql.QSqlTableModel()
        q = QtSql.QSqlQuery()
        query = """SELECT * from cars where company = 'Honda'
         """
        q.exec_(query)
        self.model.setQuery(q)
        self.proxy = FlippedProxyModel() # use flipped proxy model
        self.proxy.setSourceModel(self.model)

    def init_UI(self):
        self.grid = QGridLayout()
        self.setLayout(self.grid)
        self.table = QTableView()
        self.table.setModel(self.proxy)
        self.table.setItemDelegate(FlippedProxyDelegate(self.table)) # use flipped proxy delegate
        self.table.horizontalHeader().hide()

        self.grid.addWidget(self.table, 0, 0)

    def closeEvent(self, e):
        if (self.db.open()):
            self.db.close()

    def check_error(self, q):
        lasterr = q.lastError()
        if lasterr.isValid():
            print(lasterr.text())
            self.db.close()
            exit(1)


def main():
    app = QApplication(sys.argv)
    ex = InvertedTable("Honda")
    ex.show()

    result = app.exec_()
    sys.exit(result)


if __name__ == '__main__':
    main()      

我真的不明白问题出在哪里。为什么不能用所需的值填充表?你为什么认为使用表单布局是必要的?@Ekhumaro:是的,我能做到。查询然后填充表感觉既笨拙又不雅观,但我不知道如何使QTableModel按我想要的方式运行,所以我使用FormLayout来说明我需要什么。使用QStandardItemModel填充表要容易得多-只需反转正常的行/列循环即可。所以我还是不明白表单布局的意义。(当然,我知道这不是与数据库交互的最有效方式——我只是好奇为什么你不能使用表)。我真的不明白问题是什么。为什么不能用所需的值填充表?你为什么认为使用表单布局是必要的?@Ekhumaro:是的,我能做到。查询然后填充表感觉既笨拙又不雅观,但我不知道如何使QTableModel按我想要的方式运行,所以我使用FormLayout来说明我需要什么。使用QStandardItemModel填充表要容易得多-只需反转正常的行/列循环即可。所以我还是不明白表单布局的意义。(当然,我知道这不是与数据库交互的最有效方式——我只是好奇为什么你不能使用表)。谢谢你的指点。(特别是最后一个很有帮助-很多Qt文档对初学者来说不是很友好,很难找到这些精巧的片段。)我确实希望任何Qt的ProxyModel都可以提供翻转列和行作为选项,而不必子类,在我看来,这可能是一个常见的问题。谢谢你的指点。(特别是最后一个很有帮助——很多Qt文档对初学者不太友好,很难找到这些精巧的片段。)我确实希望任何Qt的ProxyModel都能提供翻转列和行作为一个选项,而无需子类,因为在我看来这可能是一个常见的问题。