首页 > 解决方案 > 在 QtDesigner 生成的小部件中捕获事件

问题描述

我正在尝试制作一个应用程序,允许使用鼠标(添加、移动、调整大小等)操作 QGraphicsView/QGraphicScene 中的某些对象。UI 是从 QtDesigner 生成的。我搜索的所有示例都表明鼠标事件是在主应用程序类中处理的。但是,如果有更多处理鼠标事件的小部件,我认为将鼠标逻辑单独保留在这些小部件中是明智的。我试图用单独的类来遵循这个建议,但由于我的小部件是由设计师生成的,它似乎不起作用。

我的设计师生成的代码:

# 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_())

主文件:

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_()

DesignWindowView 类将负责从 QtDesigner 生成的小部件,但这显然不起作用,并且没有捕获任何鼠标事件。我对 OOP 没有任何经验,也不完全理解子类化的概念(因为我认为这是应该这样做的方式)。

标签: pythonpyqt5qt-designer

解决方案


未捕获事件的原因是因为在从 QtDesigner 文件生成的 .py 文件中,self.DesignWindowView它仍然是一个QtWidgets.QGraphicsView对象。对此的解决方案是将QtWidgets.QGraphicsViewQt Designer 中的对象提升为DesignerWindowView对象。

为此,最好将 的定义DesignerWindowView放在一个单独的.py文件中(例如designerwindowview.py),以防止主.py文件和.py从 QtDesigner 文件生成的文件之间的循环依赖。

在设计器中,右键单击要推广的小部件并选择Promote to ...。填写提升的类名 ( DesignerWindowView)。对于头文件的名称,您应该使用不带.py扩展名的提升类的定义填写 .py 文件的名称(例如designerwindowview)。

保存并pyuic5像以前一样运行。在生成的 .py 文件 self.DesignWindowView中现在应该是一个DesignWindowView对象,并且应该有一个类似于文件from designwindowview import DesignWindowView底部的导入语句.py


推荐阅读