【写在前面】

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

python窗口内切换不同文件 python多窗口切换_多窗口

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

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

 

【示例代码】

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

MainWindow.py

# coding=utf-8
# @Auther : "鹏哥贼优秀"
# @Date : 2019/8/16
# @Software : PyCharm
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from 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")

【效果】

python窗口内切换不同文件 python多窗口切换_python_02

 

【知识点】

1、多窗口实现流程:

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

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

关键就是以下几句代码:

python窗口内切换不同文件 python多窗口切换_多窗口_03

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

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

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

python窗口内切换不同文件 python多窗口切换_多窗口_04

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

说明:

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

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

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

python窗口内切换不同文件 python多窗口切换_多窗口_05

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

 

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按钮。等我本事再提高些,再回来解决这个问题。