信号与槽是pyqt的核心机制,其目的是实现代码与控件之间的交互,真正实现对应的功能,否则控件不会有任何响应。
信号:是由对象或者控件发射出去的消息,eg:button的单击事件。
槽:接受事件的信号的代码被成为槽,槽的本质是函数或者方法。
可以把信号理解为事件,那么槽就是事件函数。

信号与槽的关系:
信号和槽之间需要绑定,一个信号可以被多个槽拦截,而一个槽也可以接受多个事件的信号。

在Qtdesigner中点击edit选择信号与槽,就可以选中窗体中的控件
 

1. 信号(signal)
其实就是事件(按钮点击 、内容发生改变 、窗口的关闭事件) 或者是 状态 (check选中了, togglebutton 切换。)

当程序触发了某种状态或者发生了某种事件(比如:按钮被点击了, 内容改变等等),那么即可发射出来一个信号。

2. 槽( slot)
若想捕获这个信号,然后执行相应的逻辑代码,那么就需要使用到 槽 , 槽实际上是一个函数, 当信号发射出来后,会执行与之绑定的槽函数

3. 将信号与槽链接
为了能够实现,当点击某个按钮时执行某个逻辑,需要把具体的信号和具体的槽函数绑定到一起.

操作大体流程如下

对象.信号.connect(槽函数)

 案例1:

简单的使用
import sys from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
class MyWindow(QWidget): def __init__(self): super().__init__() self.init_ui()
def init_ui(self): # 更改当前Widge的宽高 self.resize(500, 300) # 创建一个按钮 btn =
QPushButton("点我!", self) # 设置窗口位置、宽高 btn.setGeometry(200, 200, 100, 30) #
将按钮被点击时触发的信号与我们定义的函数(方法)进行绑定 # 注意:这里没有(),即写函数的名字,而不是名字(),目前是初始化,只有接受信号的时候才调用
btn.clicked.connect(self.click_my_btn) def click_my_btn(self, arg): #
槽函数,点击按钮则调用该函数 # 这里的参数正好是信号发出,传递的参数 print("点击按钮啦~", arg) if __name__ ==
'__main__': app = QApplication(sys.argv) w = MyWindow() w.show() app.exec()
二.自定义信号

除了接收Qt自带的信号之外,我们也可以自行定义信号,在合适的时机,自行发射信号

自定义信号需要使用到 pyqtSignal来声明信号【类变量】 ,并且需要在类中的函数之外声明

本例子中使用了两组信号和槽,一个是自定义的信号“
my_signal = pyqtSignal(str)
还有一个是系统自带的
“”clicked“”
程序运行说明:

点击“开始检测”按钮,触发槽函数“check”,
if i % 5 == 0: # 表示发射信号 对象.信号.发射(参数) self.my_signal.emit(msg + "【发现漏洞】")
同时触发上述my_signal的信号,紧接着调用“
my_slot
”函数,运行里面的代码:
import sys import time from PyQt5.QtWidgets import * from PyQt5.QtCore import
* class MyWindow(QWidget): # 声明一个信号 只能放在函数的外面 my_signal = pyqtSignal(str) def
__init__(self): super().__init__() self.init_ui() self.msg_history = list() #
用来存放消息 def init_ui(self): self.resize(500, 200) # 创建一个整体布局器 container =
QVBoxLayout() # 用来显示检测到漏洞的信息 self.msg = QLabel("") self.msg.resize(440, 15) #
print(self.msg.frameSize()) self.msg.setWordWrap(True) # 自动换行
self.msg.setAlignment(Qt.AlignTop) # 靠上 #
self.msg.setStyleSheet("background-color: yellow; color: black;") # 创建一个滚动对象
scroll = QScrollArea() scroll.setWidget(self.msg) # 创建垂直布局器,用来添加自动滚动条 v_layout
= QVBoxLayout() v_layout.addWidget(scroll) # 创建水平布局器 h_layout = QHBoxLayout()
btn = QPushButton("开始检测", self) # 绑定按钮的点击,点击按钮则开始检测
btn.clicked.connect(self.check) h_layout.addStretch(1) # 伸缩器
h_layout.addWidget(btn) h_layout.addStretch(1) # 操作将要显示的控件以及子布局器添加到container
container.addLayout(v_layout) container.addLayout(h_layout) # 设置布局器
self.setLayout(container) # 绑定信号和槽 self.my_signal.connect(self.my_slot) def
my_slot(self, msg): # 更新内容 print(msg) self.msg_history.append(msg)
self.msg.setText("<br>".join(self.msg_history)) self.msg.resize(440,
self.msg.frameSize().height() + 15) self.msg.repaint() # 更新内容,如果不更新可能没有显示新内容
def check(self): for i, ip in enumerate(["192.168.1.%d" % x for x in range(1,
255)]): msg = "模拟,正在检查 %s 上的漏洞...." % ip # print(msg) if i % 5 == 3: # 表示发射信号
对象.信号.发射(参数) self.my_signal.emit(msg + "【发现漏洞】") time.sleep(0.01) if __name__
== '__main__': app = QApplication(sys.argv) w = MyWindow() w.show() app.exec()

 

问题,在运行的过程中,如果运行过程中,移动窗口或者其他操作,可能会出现“无反应”现象

可以通过多线程解决此问题

技术
今日推荐
下载桌面版
GitHub
百度网盘(提取码:draw)
Gitee
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:766591547
关注微信