Я создаю графический интерфейс в PyQT5, который должен обеспечивать несколько представлений данных из нескольких связанных таблиц SQLite. Я реализовал эти представления для отображения через QStackedWidget.
Теперь некоторые из этих представлений предназначены для обзора, другие — для более подробного просмотра подмножества данных, отображаемых в обзорах. Я хочу получить доступ к подробным представлениям из обзоров, щелкнув правой кнопкой мыши.
Я включил минимальный пример с автомобилями ниже. (Извините, это немного длинно, но это было необходимо для предоставления полного рабочего примера. Я сократил его настолько, насколько мог.) Цель состоит в том, чтобы показать DetailledView с автомобилями компании, выбранными в обзоре.
Это уже обеспечивает доступ из Обзора к Подробному представлению при щелчке правой кнопкой мыши, но информация о компании не передается. Таким образом, даже при доступе к DetailledView из «VW» self.mycompany обновляется, а car_widget — нет, поэтому DetailledView показывает информацию об автомобилях «Honda» (по умолчанию).
Есть ли способ обновить car_widgit с помощью правильной компании? Или мне нужно создать DetailledView во время выполнения? (Это вообще работает? Но в любом случае я бы предпочел этого не делать, так как это может сделать индекс стека ненадежным...)
Как я могу обновить QTableModel одного представления в QStackedWidget в соответствии с тем, что было выбрано в другом представлении?
Вот код:
#!/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()
company
. Или вы думали, чтоmycompany
это какой-то указатель? Строки в питоне так не работают. Но в любом случае вы никогда не будете повторно вызыватьselect()
на модели, так что явно ничего не изменится. Я предлагаю вам предоставить методsetFilter()
для каждого представления и передать необходимые параметры для оператора select (и, пожалуйста, используйте заполнители, а не форматирование строк). PS: нет необходимости создавать отдельное подключение к базе данных для каждой таблицы. Достаточно одного подключения (если вы не используете многопоточность). - person ekhumoro   schedule 03.04.2018