У меня есть очень простая программа, которая открывает БД и загружает табличное представление.
So:
Файл макета с именем TestLayouts.py
# -*- coding: utf-8 -*-
################################################################################
## Form generated from reading UI file 'basic.ui'
##
## Created by: Qt User Interface Compiler version 5.14.2
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide2.QtCore import (QCoreApplication, QMetaObject,
QRect)
from PySide2.QtWidgets import *
class Ui_MainWindow(object) :
def setupUi(self, MainWindow) :
if not MainWindow.objectName() :
MainWindow.setObjectName(u"MainWindow")
MainWindow.resize(1034, 803)
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.pushButton = QPushButton(self.centralwidget)
self.pushButton.setObjectName(u"pushButton")
self.pushButton.setGeometry(QRect(920, 730, 89, 25))
self.tableView = QTableView(self.centralwidget)
self.tableView.setObjectName(u"tableView")
self.tableView.setGeometry(QRect(10, 20, 1001, 711))
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QStatusBar(MainWindow)
self.statusbar.setObjectName(u"statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QMetaObject.connectSlotsByName(MainWindow)
# setupUi
def retranslateUi(self, MainWindow) :
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
self.pushButton.setText(QCoreApplication.translate("MainWindow", u"PushButton", None))
# retranslateUi
Мой основной файл с именемtests.py
import sys
import webbrowser
from PySide2 import QtWidgets, QtGui
from PySide2.QtCore import QCoreApplication, QSortFilterProxyModel
from PySide2.QtCore import Slot
from PySide2.QtSql import QSqlDatabase, QSqlQueryModel
from PySide2.QtWidgets import QMenu, QAction
from TestLayouts import Ui_MainWindow
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow) :
def __init__(self, parent=None) :
super(MainWindow, self).__init__()
self.setupUi(self)
self.showMaximized()
self.pushButton.clicked.connect(self._basic)
def _basic(self) :
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("data.sqlite")
db.open()
sourceModel = QSqlQueryModel()
sourceModel.setQuery(
"SELECT id,url FROM database",
db)
proxyModel = QSortFilterProxyModel(self)
proxyModel.setSourceModel(sourceModel)
self.tableView.setModel(proxyModel)
self.tableView.setSortingEnabled(True)
@Slot()
def closeEvent(self, event) :
super(MainWindow, self).closeEvent(event)
QCoreApplication.instance().quit()
def contextMenuEvent(self, event) :
self.menu = QMenu(self)
openlinkAction = QAction('Open Link In A Browser', self)
openlinkAction.triggered.connect(lambda : self.openInANewTab(event))
self.menu.addAction(openlinkAction)
self.menu.popup(QtGui.QCursor.pos())
def openInANewTab(self, event) :
self.row = self.tableView.rowAt(event.pos().y())
self.col = self.tableView.columnAt(event.pos().x())
self.cell = self.tableView.item(self.row, self.col)
cellText = self.cell.text()
webbrowser.open(cellText)
if __name__ == "__main__" :
app = QtWidgets.QApplication([])
w = MainWindow()
w.show()
sys.exit(app.exec_())
Как только вы запустите программу и нажмете «Загрузить», БД загрузится в поле зрения. Меню правой кнопки мыши отображается, как и ожидалось, но при нажатии я получаю сообщение об ошибке.
RuntimeError: Internal C++ object (PySide2.QtGui.QContextMenuEvent) already deleted.
Я просмотрел несколько потоков подобных этому здесь, в котором говорится
Если QObject выходит из области видимости в Python, он будет удален. Вы должны позаботиться о сохранении ссылки на объект: сохраните его как атрибут объекта, который вы храните, например. self.window = QMainWindow()
Передать родительский объект QObject в конструктор объекта, чтобы он стал владельцем родителя
Я не уверен, как этого можно достичь. Любая помощь приветствуется.