问题
I'm trying to make an app that would allow to manipulate some objects within QGraphicsView/QGraphicScene using the mouse (adding, moving, resizing, etc.). The UI is generated from QtDesigner. All examples that I googled show that mouse events are handled from within main application class. However, if there are more widgets that deal with mouse events, I thought that it would be wise to keep the mouse logic within those widgets separately. I tried to follow this advice with separate class, but since my widgets are generated by designer, it doesn't seem to work.
My designer generated code:
# Created by: PyQt5 UI code generator 5.13.0
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.DesignWindowView = QtWidgets.QGraphicsView(self.centralwidget)
self.DesignWindowView.setGeometry(QtCore.QRect(20, 20, 761, 501))
self.DesignWindowView.setObjectName("DesignWindowView")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Main file:
import sys
from PyQt5 import QtWidgets, uic, QtGui, QtCore
from Ui_MainWindow import Ui_MainWindow
class DesignWindowView(QtWidgets.QGraphicsView):
def mousePressEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
print("Press on DesignWindowView!")
def mouseMoveEvent(self, event):
print("Mouse on DesignWindowView")
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, *args, obj=None, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.setupUi(self)
DesignWindowScene = QtWidgets.QGraphicsScene()
DesignWindowScene.addSimpleText("The Text")
self.DesignWindowView.setScene(DesignWindowScene)
self.DesignWindowView.setCursor(QtCore.Qt.CrossCursor)
self.setMouseTracking(True)
self.DesignWindowView.setMouseTracking(True)
self.show()
app = QtWidgets.QApplication(sys.argv)
# load MainWindow design
mainwindow = MainWindow()
# start the UI's event loop
app.exec_()
The DesignWindowView class would be responsible wor widget generated from QtDesigner, but this obviously doesn't work and none mouse events are catched. I don't have any experience with OOP and I don't fully understand the concept of subclassing (as I think this is the way it should be done).
回答1:
The reason the events aren't caught is because in the .py file generated from the QtDesigner file, self.DesignWindowView
is still a QtWidgets.QGraphicsView
object. The solution to this is to promote the QtWidgets.QGraphicsView
in Qt Designer to a DesignerWindowView
object.
For this it's best to put the definition of DesignerWindowView
in a separate .py
file (e.g. designerwindowview.py
) to prevent circular dependencies between the main .py
file and the .py
file generated from the QtDesigner file.
In designer, right-click on the widget that you want to promote and choose Promote to ...
. Fill in the promoted class name (DesignerWindowView
). For the name of the header file you should fill in the name of the .py file with the definition of the promoted class without the .py
extension (e.g. designerwindowview
).
Save and run through pyuic5
as before. In the generated .py file self.DesignWindowView
should now be a DesignWindowView
object, and there should be an import statement similar to from designwindowview import DesignWindowView
at the bottom of the .py
file.
来源:https://stackoverflow.com/questions/57842380/catching-events-within-qtdesigner-generated-widget