在运行时更新QStackedWidget内容

时间:2018-04-03 15:01:41

标签: python pyqt pyqt5 qstackedwidget

我在PyQT5中创建一个GUI,它应该提供来自多个相关SQLite表的数据的多个视图。我已经实现了这些视图以通过QStackedWidget显示。

现在,其中一些视图用于概述目的,其他视图用于概述中显示的数据子集的更多详细视图。我想通过右键单击概述中的详细视图。

我在下面列出了一个最小的例子。 (对不起,它有点长,但需要提供一个完整的工作示例。我尽可能地减少它。)目标是显示DetailledView与概述中选择的公司的汽车

这已经提供了从概述到Rightclick上的DetailledView的访问权限,但公司信息不会被传递。因此,即使从“VW”访问DetailledView,self.mycompany也会更新,但car_widget不会更新,因此DetailledView会显示有关' Honda'的信息。汽车(默认)。

有没有办法用合适的公司更新car_widgit?或者我是否需要在运行时创建DetailledView? (这甚至有效吗?但我不想,不管怎么说,因为它可能使得堆栈的索引不可靠......)

如何根据在另一个视图中选择的内容更新QStackedWidget中一个视图的QTableModel?

以下是代码:

#!/usr/bin/python3

from PyQt5 import QtSql
from PyQt5.QtWidgets import (QMainWindow, QWidget, QApplication, QGridLayout, 
                             QStackedWidget, QTableView, QMenu)
from PyQt5.QtCore import Qt, QModelIndex
import sys

class MainGUI(QMainWindow):
    def __init__(self):
        super().__init__()
        self.mycompany = "Honda"
        self.create_connection()
        self.fill_tables()

        self.init_UI()

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

    def fill_tables(self):
        self.db.transaction()
        q = QtSql.QSqlQuery()
        q.exec_("DROP TABLE IF EXISTS Manufacturers;")
        q.exec_("CREATE TABLE Manufacturers (CompanyId INT PRIMARY KEY, Name TEXT, Country TEXT);")
        q.exec_("INSERT INTO Manufacturers VALUES (1, 'VW', 'Germany');")
        q.exec_("INSERT INTO Manufacturers VALUES (2, 'Honda' , 'Japan');")

        q.exec_("DROP TABLE IF EXISTS Cars;")
        q.exec_("CREATE TABLE Cars (Model TEXT, Year INT, Company INT);")
        q.exec_("INSERT INTO Cars VALUES ('Civic', 2009, 'Honda');")
        q.exec_("INSERT INTO Cars VALUES ('Golf', 2013, 'VW');")
        q.exec_("INSERT INTO Cars VALUES ('Polo', 1999, 'VW');")
        self.db.commit()

    def init_UI(self):
        self.central_widget = QWidget()    
        self.setCentralWidget(self.central_widget)
        self.grid = QGridLayout()
        self.central_widget.setLayout(self.grid)
        self.setLayout(self.grid)
        self.make_stack()
        self.show()

    def make_stack(self):
        self.Stack = QStackedWidget(self)

        company_view = QWidget()
        layout = QGridLayout()
        company_view.setLayout(layout)
        self.company_widget = Overview()
        layout.addWidget(self.company_widget, 0, 0)
        self.company_widget.table.customContextMenuRequested.connect(self.open_menu)
        self.Stack.addWidget(company_view)

        car_view = QWidget()
        layout2 = QGridLayout()
        car_view.setLayout(layout2)
        car_widget = DetailedView(self.mycompany)
        layout2.addWidget(car_widget, 0, 0)
        self.Stack.addWidget(car_view)

        self.grid.addWidget(self.Stack, 0,1)

    def open_menu(self, pos):
        menu = QMenu()
        show_act = menu.addAction("Show cars")
        action = menu.exec_(self.company_widget.table.mapToGlobal(pos))
        if action == show_act:
            row = self.company_widget.table.indexAt(pos).row()
            myindex = self.company_widget.model.index(row, 1, QModelIndex())
            company = self.company_widget.model.data(myindex)
            self.mycompany = company
            self.Stack.setCurrentIndex(1)



class MyTable(QWidget):
    def __init__(self):
        super().__init__()
        self.create_connection()
        self.create_model()
        self.init_UI()

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

    def create_model(self):
        self.model = None

    def init_UI(self):
        self.grid = QGridLayout()
        self.setLayout(self.grid)
        self.table = QTableView()
        self.table.setModel(self.model)
        self.table.setContextMenuPolicy(Qt.CustomContextMenu)

        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)


class Overview(MyTable):
    def __init__(self):
        super().__init__()

    def create_model(self):
        self.model = QtSql.QSqlTableModel()
        q = QtSql.QSqlQuery()
        query = "SELECT * from Manufacturers"
        q.exec_(query)
        self.model.setQuery(q)


class DetailedView(MyTable):
    def __init__(self, company):
        self.company = company
        super().__init__()

    def create_model(self):
        self.model = QtSql.QSqlTableModel()
        q = QtSql.QSqlQuery()
        query = "SELECT * from cars where company = '{}'".format(self.company)
        q.exec_(query)
        self.model.setQuery(q)



def main():
    app = QApplication(sys.argv)
    ex = MainGUI()
    ex.show()

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


if __name__ == '__main__':
    main()      

1 个答案:

答案 0 :(得分:1)

继承的目标之一是该类实现了子进程可以执行的常见任务,在您的情况下,您不会观察这些任务,例如,模型的创建必须在父亲中完成,因为所有孩子们会这样做。

另一方面,使用QSqlTableModel的目的不是使用df <- read.table(text = "1 rs22233… B B B B B B B B B B B 2 rs38622… B B B B B B B B A B A 3 rs13933… B B A B B B B B B B B 4 rs38637… B B A A A B B B A B A 5 rs12554… B B B B A B A B B B B 6 rs41105… A A A A B A B A A A B ", row.names = 1) ,而是更友好的请求,例如QSqlQuerysetTable()select(),但它只是一个浪费,因为你可以使用setFilter()

另一方面,我发现您假设QSqlQueryModel的{​​{1}}与self.mycompany的{​​{1}}相同,因为您正在经历创建DetailView对象,事实是它们不一样,在创建对象时只复制了那个时刻的值,所以如果你改变了MainGui self.company它不会更改DetailedView的{​​{1}}。

重组您的项目,您将获得以下内容:

self.company