zoukankan      html  css  js  c++  java
  • 大爽pyqt5笔记&教程 三 信号和槽 Signals & Slots 实现窗口跳转、返回、恢复、传参

    作者自我介绍:大爽歌, b站小UP主
    python1对1辅导老师
    时常直播编程,直播时免费回答简单问题。

    6 信号与槽

    信号和槽一般用于多个窗口之间传递信息,
    或者前后端传递信息。

    定义信号

    一般在class下面开头定义。
    (pyqt 里面定义新对象时,如果不需要专门继承特定对象,推荐继承PyQt5.QtCore.QObject)

    比如

    from PyQt5.QtCore import QObject, pyqtSignal
    
    class A(QObject):
        sign_one = pyqtSignal()
    

    其中sign_one就是我们定义的信号,是PyQt5.QtCore.pyqtSignal的一个实例。

    发射信号与绑定方法

    发射信号很简单,使用emit方法就可以了。
    示例

    self.sign_one.emit()
    

    但是这个时候不会有效果,因为没有给信号绑定方法(槽函数)。

    需要使用connect方法,给信号绑定对应的方法。
    然后发射信号时,其绑定的方法就会被调用。
    绑定语句示例

    self.sign_one.connect(someclass.method)
    

    一个信号可以绑定多个槽函数,也就是可以给多个槽发信号。
    一个槽函数也可以响应多个信号。

    信号传递参数

    有的时候我们需要传递参数,让槽函数能够接受这些参数来运行。
    那么这个时候的改动有这几处

    1. 定义信号时,定义需要传递的参数类型。
      比如字符串str,整数int,甚至字典dict列表list
    2. 发射信号时,传参。
    3. 接受信号的槽函数,要接受参数。

    1的示例

    from PyQt5.QtCore import QObject, pyqtSignal
    
    class A(QObject):
        sign_str = pyqtSignal(str)
        sign_int = pyqtSignal(int)
        sign_dict = pyqtSignal(dict)
        sign_list = pyqtSignal(list)
    

    2的示例

    self.sign_str.emit("a string")
    self.sign_int.emit(1)
    self.sign_dict.emit({"a": 1})
    self.sign_list.emit([1, 2, 3])
    

    3 的示例就不太容易举了,因为这个取决于方法,
    即绑定的method能接受对应的参数并处理。

    具体可以看后面的例子了

    小结

    信号与槽的使用,主要就是上面三步走,

    • 定义信号
    • 发射信号
    • 绑定方法

    7 窗口跳转

    场景分析

    希望实现的场景:A窗口中,点击按钮,打开B窗口,同时不再显示A窗口。

    分析:
    不显示一个窗口,一般使用隐藏。

    实现代码

    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import pyqtSignal
    
    import sys
    
    
    class Window_A(QWidget):
        sign_one = pyqtSignal()
    
        def __init__(self):
            super(Window_A, self).__init__()
            self.init_gui()
    
        def init_gui(self):
            self.label = QLabel("Window A", self)
            self.label.move(40, 20)
    
            self.button = QPushButton('Open new Window', self)
            self.button.move(150, 20)
            self.button.clicked.connect(self.click_button)
    
        def click_button(self):
            self.sign_one.emit()
            self.hide()
    
    
    class Window_B(QWidget):
    
        def __init__(self):
            super(Window_B, self).__init__()
            self.init_gui()
    
        def init_gui(self):
            self.label = QLabel("This is window B", self)
            self.label.move(40, 20)
    
        def method_handle_sign(self):
            self.show()
    
    
    app = QApplication(sys.argv)
    
    win_a  = Window_A()
    win_b = Window_B()
    
    win_a.sign_one.connect(win_b.method_handle_sign)
    
    win_a.show()
    
    sys.exit(app.exec_())
    

    A窗口效果

    点击按钮打开B窗口
    B窗口效果

    8 窗口传参

    场景分析

    希望实现的场景:
    A窗口,作为简易登录窗口。
    有输入框用于输入名字。
    点击按钮,将名字发送给B窗口。

    B窗口保存名字信息并展示,同时不再显示A窗口。

    分析:
    要传递名字,一般使用字符串形式传递,此时信号中要能够传递字符串信息。

    实现代码

    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import pyqtSignal
    
    import sys
    
    
    class Window_A(QWidget):
        sign_two = pyqtSignal(str)
    
        def __init__(self):
            super(Window_A, self).__init__()
            self.resize(300, 200)
            self.init_gui()
    
        def init_gui(self):
            label = QLabel("Login Page", self)
            label.move(40, 20)
    
            input_label = QLabel("Enter your name", self)
            input_label.move(20, 50)
    
            self.input_form = QLineEdit("", self)
            self.input_form.move(20, 80)
    
            self.button = QPushButton('confirm', self)
            self.button.move(40, 110)
            self.button.clicked.connect(self.click_button)
    
        def click_button(self):
            name = self.input_form.text()
            self.sign_two.emit(name)
            self.hide()
    
    
    class Window_B(QWidget):
    
        def __init__(self):
            super(Window_B, self).__init__()
            self.name = ""
            self.init_gui()
    
        def init_gui(self):
            label = QLabel("Welcome", self)
            label.move(40, 20)
    
            self.name_label = QLabel(self.name, self)
            self.name_label.move(40, 50)
    
    
        def method_handle_sign2(self, name):
            self.name = name
            self.name_label.setText(self.name)
            self.show()
    
    
    app = QApplication(sys.argv)
    
    win_a  = Window_A()
    win_b = Window_B()
    
    win_a.sign_two.connect(win_b.method_handle_sign2)
    
    win_a.show()
    
    sys.exit(app.exec_())
    

    A窗口效果

    此时输入框中输入BigShuang并点击confirm按钮。

    会打开窗口B, 如下

    9 窗口返回与恢复

    场景分析

    希望实现的场景:
    B窗口,是一个游戏主窗口,展示当前关卡信息和几个按钮。
    点击不同的按钮,可以发送不同的游戏结算信息给结算窗口C并展示C,且不显示B窗口。

    C窗口展示结算信息,
    C窗口有按钮进入下一关,
    点击此按钮会展示B窗口进入下一关,再次隐藏C窗口。

    分析:
    要传递较多的信息,可以使用字典或者列表来传递,这里推荐使用字典。
    此时信号中要能够传递字典信息。

    代码实现

    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import pyqtSignal
    
    import sys
    
    
    class Window_B(QWidget):
        sign_three = pyqtSignal(dict)
    
        def __init__(self):
            super(Window_B, self).__init__()
    
            self.name = "BigShuang"
            self.level = 1
            self.score = 0
    
            self.setWindowTitle("Game")
            self.resize(300, 200)
            self.init_gui()
    
        def init_gui(self):
            label1 = QLabel("Welcome", self)
            label1.move(40, 20)
    
            self.name_label = QLabel(self.name, self)
            self.name_label.move(40, 50)
    
            label2 = QLabel("Choose one button", self)
            label2.move(40, 80)
    
            button_1 = QPushButton("1", self)
            button_1.move(20, 110)
    
            button_2 = QPushButton("2", self)
            button_2.move(150, 110)
    
            button_1.clicked.connect(self.ending_1)
            button_2.clicked.connect(self.ending_2)
    
        def ending_1(self):
            self.score += 10
            self.send_info()
    
        def ending_2(self):
            self.score += 20
            self.send_info()
    
        def send_info(self):
            info = {
                "name": self.name,
                "level": self.level,
                "score": self.score
            }
            self.hide()
            self.sign_three.emit(info)
    
        def next_level(self):
            self.level += 1
            self.show()
    
    
    class Window_C(QWidget):
        sign_four = pyqtSignal()
    
        def __init__(self):
            super(Window_C, self).__init__()
    
            self.resize(300, 200)
            self.setWindowTitle("Result")
            self.init_gui()
    
        def init_gui(self):
            label1 = QLabel("Name: ", self)
            label2 = QLabel("Level: ", self)
            label3 = QLabel("score: ", self)
            self.name_label = QLabel("", self)
            self.level_label = QLabel("", self)
            self.score_label = QLabel("", self)
    
            button = QPushButton("Next Level", self)
    
            label1.move(20, 20)
            label2.move(20, 50)
            label3.move(20, 80)
    
            self.name_label.move(100, 20)
            self.level_label.move(100, 50)
            self.score_label.move(100, 80)
    
            button.move(60, 110)
            button.clicked.connect(self.click_button)
    
        def show_result(self, info):
            self.name_label.setText(info["name"])
            self.level_label.setText(str(info["level"]))
            self.score_label.setText(str(info["score"]))
    
            self.show()
    
        def click_button(self):
            self.sign_four.emit()
    
    app = QApplication(sys.argv)
    
    win_b = Window_B()
    win_c = Window_C()
    
    win_b.sign_three.connect(win_c.show_result)
    win_c.sign_four.connect(win_b.next_level)
    win_c.sign_four.connect(win_c.hide)
    
    win_b.show()
    
    sys.exit(app.exec_())
    

    运行该代码,会先展示窗口B
    如下

    此时点击按钮1和按钮2都会进入结算界面C。
    (点击按钮1总分加10,按钮2总分加20)

    比如点击按钮2进入结算界面,效果如下

    此时点击Next Level会进入下一关,即隐藏结算界面,并再展示窗口B。
    (且窗口B内部的关卡信息已更新)

  • 相关阅读:
    理解 Javascript 执行上下文和执行栈
    CSS中选择器优先级的权重计算
    一年内经验前端面试题记录
    ie8兼容问题
    css文本两端对齐
    前端 SPA 单页应用数据统计解决方案 (ReactJS / VueJS)
    我在SharePoint行业的从业经历(一)
    android中的AlertDialog具体概述
    Android 最火的高速开发框架xUtils
    Project Euler:Problem 93 Arithmetic expressions
  • 原文地址:https://www.cnblogs.com/BigShuang/p/15564213.html
Copyright © 2011-2022 走看看