【Python成长之路】从零学GUI -- 多窗口跳转、信号传递(信号与槽函数用法)

【写在前面】

    自学python,不同于工作上的代码编程,主要是为了好玩或者满足自己的需求。因此,我一直想自己做些APP,未来可以给小朋友做做练习,比如让她学习算术、学习成语接龙之类的。总不能让她看这样恐怖的界面吧?

因此,就自学GUI,可以制作些可视化界面工具。

    另外,我在制作GUI时,发现多窗口之间的信号传递和处理特别麻烦,网上有很多C或者JAVA的帖子,或者只有 介绍如何显示多窗口,但是就是没有详细的Python介绍如何实现信号传递。因此也希望这篇文章有点用吧!

 

【示例代码】

示例代码一共有2份,一份是主窗口的代码 ,一份是子窗口的代码。

MainWindow.py

# coding=utf-8# @Auther : "鹏哥贼优秀"# @Date : 2019/8/16# @Software : PyCharm
from PyQt5 import QtCore, QtGui, QtWidgetsimport sysfrom ChildWindow import *
class Ui_MainWindow(QtWidgets.QMainWindow):    def setupUi(self, Dialog):        Dialog.setObjectName("Dialog")        Dialog.resize(534, 386)        self.pushButton = QtWidgets.QPushButton(Dialog)        self.pushButton.setGeometry(QtCore.QRect(360, 140, 101, 51))        self.pushButton.setStyleSheet("background-color: rgb(0, 255, 127);\n""font: 12pt \"黑体\";")        self.pushButton.setObjectName("pushButton")        self.plainTextEdit = QtWidgets.QPlainTextEdit(Dialog)        self.plainTextEdit.setGeometry(QtCore.QRect(50, 120, 271, 161))        self.plainTextEdit.setStyleSheet("font: 11pt \"宋体\";")        self.plainTextEdit.setObjectName("plainTextEdit")        self.label = QtWidgets.QLabel(Dialog)        self.label.setGeometry(QtCore.QRect(60, 85, 131, 21))        self.label.setStyleSheet("font: 12pt \"黑体\";\n""color: rgb(255, 0, 0);")        self.label.setObjectName("label")
        self.retranslateUi(Dialog)        QtCore.QMetaObject.connectSlotsByName(Dialog)
    def retranslateUi(self, Dialog):        _translate = QtCore.QCoreApplication.translate        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))        self.pushButton.setText(_translate("Dialog", "弹出子窗口"))        self.label.setText(_translate("Dialog", "显示子窗口内容"))        self.pushButton.clicked.connect(self.btn)        # 在主窗口点击按钮后,显示子窗口    def btn(self):        self.child = QtWidgets.QDialog()        self.childwindow = Ui_ChildWindow()        self.childwindow.setupUi(self.child)        # 与子窗口的信号连接        self.childwindow.my_signal.connect(self.child_click)        self.child.show()
    # 定义子窗口的按钮作用    def child_click(self):        value = self.childwindow.plainTextEdit.toPlainText()        print(value)        self.childwindow.plainTextEdit.setPlainText("子窗口输入成功!")        self.plainTextEdit.setPlainText(value)
if __name__ == "__main__":    app = QtWidgets.QApplication(sys.argv)    main = QtWidgets.QMainWindow()    mainwindow = Ui_MainWindow()    mainwindow.setupUi(main)    main.show()    sys.exit(app.exec())

ChildWindow.py

# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_ChildWindow(QtWidgets.QDialog):    # 声明信号    my_signal = QtCore.pyqtSignal(str)    def setupUi(self, Dialog):        Dialog.setObjectName("Dialog")        Dialog.resize(565, 413)        self.pushButton = QtWidgets.QPushButton(Dialog)        self.pushButton.setGeometry(QtCore.QRect(400, 120, 75, 51))        self.pushButton.setStyleSheet("font: 12pt \"黑体\";\n""background-color: rgb(0, 255, 127);")        self.pushButton.setObjectName("pushButton")        self.plainTextEdit = QtWidgets.QPlainTextEdit(Dialog)        self.plainTextEdit.setGeometry(QtCore.QRect(90, 110, 261, 111))        self.plainTextEdit.setStyleSheet("font: 12pt \"宋体\";")        self.plainTextEdit.setObjectName("plainTextEdit")
        self.retranslateUi(Dialog)        QtCore.QMetaObject.connectSlotsByName(Dialog)
    def retranslateUi(self, Dialog):        _translate = QtCore.QCoreApplication.translate        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))        self.pushButton.setText(_translate("Dialog", "输入"))        self.pushButton.clicked.connect(self.click)
    # 信号传递回主窗口并结束    def click(self):        self.my_signal.emit("1")

【效果】

 

【知识点】

1、多窗口实现流程:

(1)用QT Designer直接先设计好主、子窗口的界面布局及按钮制作(如何使用Qt Designer,这块知识网上 有很多,暂不介绍了)

(2)在子窗口中,定义窗口的信号,及定义好信号发送后的退出方式。

关键就是以下几句代码:

因为我定义了my_signal信号,并且要求发送str作为信号的结束。因此在click方法中,定义成了my_signal.emit("1")。表示这个信号发送了“1”给主窗口,并结束。但其实,这个地方“1”并没有什么意义,因为我只是需要多窗口之间的信号连接,不关心最后子窗口给我返回的是什么。

(3)主窗口这边就有2个功能要实现了。

一方面除了显示主窗口界面外,还要在点击按钮后显示子窗口界面,如下图:

这 段代码还 是好理解的,在点击主窗口按钮后,调用窗口显示流程代码 + 一句与子窗口信号连接的代码 。但其实这段 代码就是多窗口实现的核心代码。刚开始学习的时候,就是这段流程不 熟悉,所以一直碰壁。

说明:

其实子窗口与主窗口显示的代码流程是一样的,只是子窗口属于QDialog类,主窗口属于QMainWindow类布局。

因为信号连接的代码是表示子窗口点击了按钮后,程序应当进入child_click方法。

下面就是子窗口按钮响应的实现了。

具体功能就是根据各自需求实现了。

 

2、别以为 上面这样就可以了,但是 有个坑 :

如果是通过Qt Designer实现代码转换的话,类定义一般是:

class Ui_MainWindow(object):

发现没,一般是不会声明具体继承什么类,导致主、子窗口的类继承冲突(这里我对类继承也不太熟悉,不知道要怎么解释)。查过网上的一些资料,说主、子窗口的类型不能一样,即不能都为QDialog,所以要把各个类声明好,具体是继承什么类的。即如下:

class Ui_MainWindow(QtWidgets.QMainWindow):

 

3、聊聊多窗口数据传递的方法

我当前想到有3个办法 可以实现多窗口信号传递。

(1)子窗口将要传递的信号,写到一个临时文件中,然后主窗口读取临时文件。这个就是文件读写的操作了,但是比较土。

(2)在主窗口中,获取到子窗口内的信号。本文采用的就是这种方法。

(3)在子窗口中,直接把主 窗口的内容进行修改。理论上应该只要继承父类就可以了 ,如下

import MainWindow

class Ui_ChildWindow(MainWindow.Ui_MainWindow):

但是可能是 我使用方式有问题,无法访问父类的对象,即无法获取 到父类的Pushbutton按钮。等我本事再提高些,再回来解决这个问题。

 

【写在最后】

    如果觉得不错,关注我公众号“鹏哥贼优秀”呀!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值