在 QtDesigner 生成的小部件中捕获事件 [英] Catching events within QtDesigner generated widget

查看:64
本文介绍了在 QtDesigner 生成的小部件中捕获事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

主文件:

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 没有任何经验,也不完全理解子类化的概念(因为我认为这是应该完成的方式).

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).

推荐答案

事件没有被捕获的原因是因为在从 QtDesigner 文件生成的 .py 文件中,self.DesignWindowView 仍然是QtWidgets.QGraphicsView 对象.对此的解决方案是将 Qt Designer 中的 QtWidgets.QGraphicsView 提升为 DesignerWindowView 对象.

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.

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

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.

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

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).

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

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.

这篇关于在 QtDesigner 生成的小部件中捕获事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆