信号与槽
-
信号:
其实就是事件(按钮点击 、内容发生改变 、窗口的关闭事件) 或者是 状态 (check选中了, togglebutton 切换)
当程序触发了某种状态或者发生了某种事件(比如:按钮被点击了, 内容改变等等),那么即可发射出来一个
信号
。 -
槽
若想捕获这个信号,然后执行相应的逻辑代码,那么就需要使用到
槽
,槽
实际上是一个函数, 当信号
发射出来后,会执行与之绑定的槽
函数 -
对象.信号.connect(槽函数)
案例一:遍历并动态输出字符串
# -*- coding: utf-8 -*-
# 学习时间: 2022/10/27 17:11
__author__ = 'He XK'
import sys
import time
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class MyWindow(QWidget):
# 在内部函数外定义全局变量
# 传入参数为str,表示可以接受一个字符串的信号参数
my_signal = pyqtSignal(str)
def __init__(self):
super(MyWindow, self).__init__()
self.container_init()
# 定义一个列表,用于存放输入输入进去的信息
self.info_history = []
def container_init(self):
self.resize(500, 300)
# 整体框架的垂直布局
container_v_layout = QVBoxLayout()
# 创建一个Label对象
# 用Label来显示信息
self.info_label = QLabel('')
self.info_label.resize(400, 15)
# 设置自动换行
self.info_label.setWordWrap(True)
self.info_label.setAlignment(Qt.AlignTop)
# 创建一个滚动条对象
scroll = QScrollArea()
scroll.setWidget(self.info_label)
# 创建垂直布局器
v_layout = QVBoxLayout()
v_layout.addWidget(scroll)
# 水平布局器存放按钮
# 并通过弹簧让其居中显示
h_layout = QHBoxLayout()
btn = QPushButton('开始检测', self)
btn.clicked.connect(self.btn_check)
h_layout.addStretch(1)
h_layout.addWidget(btn)
h_layout.addStretch(1)
container_v_layout.addLayout(v_layout)
container_v_layout.addLayout((h_layout))
self.setLayout(container_v_layout)
self.my_signal.connect(self.signal_slot)
# 与信号绑定的槽函数
# 传入的info是一个字符串
def signal_slot(self, info):
# 打印info字符串
print(info)
# 在self对象属性的info_history列表中新增传递的info
self.info_history.append(info)
# 重新设置label元素的文本
# 本身只是一个info_label
# 重新设置文本,用字符串拼接。
self.info_label.setText('\n'.join(self.info_history))
# 重新调整文本的高
self.info_label.resize(400, 15 * len(self.info_history))
# 更新内容
self.info_label.repaint()
def btn_check(self):
for index, item in enumerate(["192.168.1.%d" % x for x in range(1, 256)]):
info = '正在检查 %s 的漏洞...' % item
if index % 6 == 0:
self.my_signal.emit(info + '|| 发现漏洞 ||')
time.sleep(0.01)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
以一个滚动栏的形式显示检查的内容,所有的内容是有一个列表拼接而成的字符串。
首先在类中声明一个信号,这个信号可以传递一个字符串。
my_signal = pyqtSignal(str)
定义初始化函数,并且新建self.msg_history = list()
用于存储信息。
def __init__(self):
super().__init__()
self.init_ui()
self.msg_history = list() # 用来存放消息
定义一个与信号绑定的槽函数。
目的是修改并更新info_history
的内容;
先给该列表追加传入的info
,之后执行self.info_label.setText('\n'.join(self.info_history)
用于将该列表中的所有内容拼接成一个字符串;
此时的主窗体中仍是只有一个Label
控件,所以要重新设置控件的大小,使用self.info_label.resize(400, 15 * len(self.info_history)
调整info_label
控件大小;
最后刷新该控件self.info_label.repaint()
# 与信号绑定的槽函数
# 传入的info是一个字符串
def signal_slot(self, info):
# 打印info字符串
print(info)
# 在self对象属性的info_history列表中新增传递的info
self.info_history.append(info)
# 重新设置label元素的文本
# 本身只是一个info_label
# 重新设置文本,用字符串拼接。
self.info_label.setText('\n'.join(self.info_history))
# 重新调整文本的高
self.info_label.resize(400, 15 * len(self.info_history))
# 更新内容
self.info_label.repaint()
窗体UI函数,这一部分内容较多。
整体的主窗体可以分为两个布局,主体的垂直布局和下方的水平布局。
所有的信息文本是通过Label
控件显示,先声明一个空的Label
控件,设定其大小,同时注意self.info_label.setWordWrap(True)
实现根据文本中的内容自动换行;self.info_label.setAlignment(Qt.AlignTop)
实现整体文本的置顶,若不加这句话会导致文本控件慢慢向下。
声明一个滚动条对象QScrollArea()
,并设定一个小组件,当小组件超出固定大小的范围时生成滚动条。
题外话:还具有QScrollBar
组件,可以生成水平和垂直的滚动条。
最后,为信号绑定槽函数。
def container_init(self):
self.resize(500, 300)
# 整体框架的垂直布局
container_v_layout = QVBoxLayout()
# 创建一个Label对象
# 用Label来显示信息
self.info_label = QLabel('')
self.info_label.resize(400, 15)
# 设置自动换行
self.info_label.setWordWrap(True)
self.info_label.setAlignment(Qt.AlignTop)
# 创建一个滚动条对象
scroll = QScrollArea()
scroll.setWidget(self.info_label)
# 创建垂直布局器
v_layout = QVBoxLayout()
v_layout.addWidget(scroll)
# 水平布局器存放按钮
# 并通过弹簧让其居中显示
h_layout = QHBoxLayout()
btn = QPushButton('开始检测', self)
btn.clicked.connect(self.btn_check)
h_layout.addStretch(1)
h_layout.addWidget(btn)
h_layout.addStretch(1)
container_v_layout.addLayout(v_layout)
container_v_layout.addLayout((h_layout))
self.setLayout(container_v_layout)
self.my_signal.connect(self.signal_slot)
点击函数部分。
def btn_check(self):
for index, item in enumerate(["192.168.1.%d" % x for x in range(1, 256)]):
info = '正在检查 %s 的漏洞...' % item
if index % 6 == 0:
self.my_signal.emit(info + '|| 发现漏洞 ||')
time.sleep(0.01)
案例二:滑动条改变字体颜色
# -*- coding: utf-8 -*-
# 学习时间: 2022/10/27 19:45
__author__ = 'He XK'
import sys
import time
from PyQt5.QtGui import QPalette, QColor
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class MyWindow(QWidget):
def __init__(self):
super(MyWindow, self).__init__()
self.container_init()
def container_init(self):
# 程序垂直布局
v_layout = QVBoxLayout()
# 程序主体水平布局
h_layout = QHBoxLayout()
# 声明一段文字label
self.label = QLabel('Drag scrollbar sliders to change color!!!')
self.label.setStyleSheet('font-size: 20px;')
v_layout.addWidget(self.label)
# 生成三个滑动条对象
self.scroll1 = QScrollBar(Qt.Horizontal)
self.scroll2 = QScrollBar(Qt.Horizontal)
self.scroll3 = QScrollBar(Qt.Horizontal)
# 设定滑动条代表的最大值255
self.scroll1.setMaximum(255)
self.scroll2.setMaximum(255)
self.scroll3.setMaximum(255)
# 绑定函数
self.scroll1.sliderMoved.connect(self.slider_fun)
self.scroll2.sliderMoved.connect(self.slider_fun)
self.scroll3.sliderMoved.connect(self.slider_fun)
v_layout.addWidget(self.scroll1)
v_layout.addWidget(self.scroll2)
v_layout.addWidget(self.scroll3)
self.setLayout(v_layout)
self.resize(400, 400)
def slider_fun(self):
print(self.scroll1.value(), self.scroll2.value(), self.scroll3.value())
palette = QPalette()
color = QColor(self.scroll1.value(), self.scroll2.value(), self.scroll3.value(), 255)
palette.setColor(QPalette.Foreground, color)
self.label.setPalette(palette)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
QScrollBar
可以生成水平或垂直方向的滑动条。参数Qt.Horizontal
生成水平方向,默认是垂直方向。
QPalette
是调色板。