Catching events within QtDesigner generated widget

烂漫一生 提交于 2020-01-16 09:12:04

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!