PySide6 信号、槽

信号与槽的入门应用(一):https://blog.csdn.net/jia666666/article/details/81774175
信号与槽的再细分(二):https://blog.csdn.net/jia666666/article/details/81774858
信号与槽的高级玩法(三):https://blog.csdn.net/jia666666/article/details/81775378
信号与槽的高级用法(四):https://blog.csdn.net/jia666666/article/details/81775614
Qt Designer神助攻(五):https://blog.csdn.net/jia666666/article/details/81780619
多线程中信号与槽的使用(六):https://blog.csdn.net/jia666666/article/details/81780930
多窗口数据传递(七):https://blog.csdn.net/jia666666/article/details/81781697
事件处理机制(八):https://blog.csdn.net/jia666666/article/details/81781992

1、根据 使用 进行分类

1. 内置信号、内置

内置信号与槽的使用,是指在发射信号时,使用窗口控件的函数,而不是自定义的函数,这种也是我们前面用的最多。示例:

# -*- coding: utf-8 -*-import sys
from PySide6.QtWidgets import QMessageBox, QPushButton, QApplication, QWidgetdef show_msg():QMessageBox.information(widget, '信息提示框', 'Ok 弹出测试信息')app = QApplication(sys.argv)
widget = QWidget()
btn = QPushButton('测试点击按钮', widget)
btn.clicked.connect(show_msg)
widget.resize(300, 300)
widget.show()
sys.exit(app.exec())

这个例子将一个按钮对象的内置clicked信号与自定义槽函数show_msg() 连接。单击按钮,就会触发这个槽函数,弹出一个信息提示框

2. 自定义信号、自定义槽

自定义信号与槽的使用:是指在发射信号时,不使用窗口控件的函数,而是使用自定义的函数,(简单的说就是使用oyqtsSignal类实例发射信号),之所以要使用自定义的信号与槽,是因为通过内置函数发射信号有自身的缺陷,首先,内置函数只包含一些常用地信号,有些信号发射找不到对应的内置函数,其次在特定的情况下,才能发射此信号,如按钮的点击事件,最后,内置函数传递的参数是特定的,不可以自定义,使用自定义的信号与槽函数则没有这些缺陷

在pyqt5中,自定义信号与槽的适用很灵活,比如因为业务需要,在程序中的某些地方需要发射一个信号,传递多种数据,然后在槽函数接受这些数据,这样就可以很灵活的实现一些业务逻辑

简单的一个实例:简单的自定义信号与槽

import sys
from PySide6 import QtCore# 定义一个名字叫 say_some_words 的 slot, 并接收string
@QtCore.Slot(str)
def say_some_words(words):print(words)# 信号对象
class Communicate(QtCore.QObject):# 创建一个名字叫 speak 的信号speak = QtCore.Signal(str)some_one = Communicate()
# connect signal and slot
some_one.speak.connect(say_some_words)
# emit 'speak' signal
some_one.speak.emit("Hello everybody!")

添加重载:

import sys
from PySide6 import QtCore# define a new slot that receives a C 'int' or a 'str'
# and has 'saySomething' as its name
@QtCore.Slot(int)
@QtCore.Slot(str)
def say_something(stuff):print(stuff)class Communicate(QtCore.QObject):# create two new signals on the fly: one will handle# int type, the other will handle stringsspeakNumber = QtCore.Signal(int)speakWord = QtCore.Signal(str)someone = Communicate()
# connect signal and slot properly
someone.speakNumber.connect(say_something)
someone.speakWord.connect(say_something)
# emit each 'speak' signal
someone.speakNumber.emit(10)
someone.speakWord.emit("Hello everybody!")

使用槽重载以及一些复杂的信号连接及发射

import sys
from PySide6 import QtCore# define a new slot that receives an C 'int' or a 'str'
# and has 'saySomething' as its name
@QtCore.Slot(int)
@QtCore.Slot(str)
def say_something(stuff):print(stuff)class Communicate(QtCore.QObject):# create two new signals on the fly: one will handle# int type, the other will handle stringsspeak = QtCore.Signal((int,), (str,))someone = Communicate()
# connect signal and slot. As 'int' is the default
# we have to specify the str when connecting the
# second signal
someone.speak.connect(say_something)
someone.speak[str].connect(say_something)# emit 'speak' signal with different arguments.
# we have to specify the str as int is the default
someone.speak.emit(10)
someone.speak[str].emit("Hello everybody!")

示例:

import sys
from PySide6.QtCore import QObject, Signal, Slot"""
PyQt使用了另外一种方式。为了将PyQt脚本转而使用PySide运行
只需要使用下面的代码进行修改。
from PySide.QtCore import Signal as pyqtSignal
from PySide.QtCore import Slot as pyqtSlot
或者
QtCore.pyqtSignal = QtCore.Signal
QtCore.pyqtSlot = QtCore.Slot
"""# 信号对象
class CustomSignal(QObject):# 定义一个信号signal_send_msg = Signal(str, str)def __init__(self):super(CustomSignal, self).__init__()def run(self):# 发射信号# self.sendmsg.emit('hell')# 发射多个参数self.signal_send_msg.emit('第一参数', '第二个参数')# 槽对象
class CustomSlot(QObject):def __init__(self):super(CustomSlot, self).__init__()self.temp = None# 槽对象中的槽函数# def get( self,msg ):#     print("QSlot get msg => " + msg)# 多个参数def get_msg(self, msg1, msg2):self.temp = Noneprint("QSlot get msg => " + msg1 + ' ' + msg2)if __name__ == '__main__':custom_signal = CustomSignal()  # 实例化信号对象custom_slot = CustomSlot()    # 实例化槽对象# 把信号绑定到槽函数上custom_signal.signal_send_msg.connect(custom_slot.get_msg)custom_signal.run()# 把信号与槽函数解绑custom_signal.signal_send_msg.disconnect(custom_slot.get_msg)custom_signal.run()

3. 装饰器的信号、槽

所谓装饰器信号与槽,就是通过 装饰器 的方法来定义信号与槽函数

示例:通过 @QtCore.Slot(str) 装饰一个函数,把函数变成一个 槽函数

import sys
from PySide6 import QtCore# 定义一个名字叫 say_some_words 的 slot, 并接收string
@QtCore.Slot(str)
def say_some_words(words):print(words)# 信号对象
class Communicate(QtCore.QObject):# 创建一个名字叫 speak 的信号speak = QtCore.Signal(str)some_one = Communicate()
# connect signal and slot
some_one.speak.connect(say_some_words)
# emit 'speak' signal
some_one.speak.emit("Hello everybody!")

2、根据信号与槽各自的性质分类

内置信号、内置槽函数

演示单击时关闭窗口,使用内置的信号与槽函数

# -*- coding: utf-8 -*-from PySide6.QtWidgets import *
import sysclass WinForm(QWidget):def __init__(self, parent=None):super().__init__(parent)self.setWindowTitle('内置的信号/槽示例')self.resize(300, 150)btn = QPushButton('关闭', self)btn.clicked.connect(self.close)if __name__ == '__main__':app = QApplication(sys.argv)win = WinForm()win.show()sys.exit(app.exec())

内置信号、自定义槽函数

# -*- coding: utf-8 -*-from PySide6.QtWidgets import *
import sysclass WinForm(QWidget):def __init__(self, parent=None):super().__init__(parent)self.setWindowTitle('内置的信号和自定义槽函数示例')self.resize(300, 150)btn = QPushButton('关闭', self)btn.clicked.connect(self.btn_close)def btn_close(self):# 自定义槽函数self.close()if __name__ == '__main__':app = QApplication(sys.argv)win = WinForm()win.show()sys.exit(app.exec())

自定义信号、内置槽函数

# -*- coding: utf-8 -*-import sys
from PySide6 import QtCore
from PySide6.QtWidgets import *class WinForm(QWidget):# 自定义信号,不带参数button_clicked_signal = QtCore.Signal()def __init__(self, parent=None):super().__init__(parent)self.setWindowTitle('自定义信号和内置槽函数示例')self.resize(300, 150)btn = QPushButton('关闭', self)# 连接 信号和槽btn.clicked.connect(self.btn_clicked)# 接收信号,连接到槽self.button_clicked_signal.connect(self.close)def btn_clicked(self):# 发送自定义信号,无参数self.button_clicked_signal.emit()if __name__ == '__main__':app = QApplication(sys.argv)win = WinForm()win.show()sys.exit(app.exec())

自定义信号、自定义槽函数

# -*- coding: utf-8 -*-import sys
from PySide6 import QtCore
from PySide6.QtWidgets import *class WinForm(QWidget):# 自定义信号,不带参数button_clicked_signal = QtCore.Signal()def __init__(self, parent=None):super().__init__(parent)self.setWindowTitle('自定义信号和槽函数示例')self.resize(300, 150)btn = QPushButton('关闭', self)# 连接 信号和槽btn.clicked.connect(self.btn_clicked)# 接收信号,连接到自定义槽函数self.button_clicked_signal.connect(self.btn_close)def btn_clicked(self):# 发送自定义信号,无参数self.button_clicked_signal.emit()def btn_close(self):self.close()if __name__ == '__main__':app = QApplication(sys.argv)win = WinForm()win.show()sys.exit(app.exec())

3、信号、槽 高级用法

所谓高级,就是自定义信号与槽时,可以传递参数。

自定义信号一般流程

定义信号

定义槽函数

连接信号与槽函数

发射信号

定义 信号

通过 类成员变量 定义信号对象

signal1 = QtCore.Signal()          # 无参数的信号
signal2 = QtCore.Signal(int)       # 带一个参数(整数)的信号
signal3 = QtCore.Signal(int, str)  # 带两个参数(整数,字符串)的信号
signal4 = QtCore.Signal(list)      # 带一个参数(列表)的信号
signal5 = QtCore.Signal(dict)      # 带一个参数(字典)的信号
signal6 = QtCore.Signal([int, str], [str])  # 带(整数 字符串)或者(字符串)的信号

定义 槽函数

定义一个槽函数,它有多个不同的输入参输数

def signal_call_1(self):print("signal1 emit")def signal_call_2(self, val):print('signal2 emit,value:', val)def signal_call_3(self, val, text):print('signall3 emit,value:', val, text)def signal_call_4(self, val):print('signal4 emit,value:', val)def signal_call_5(self, val):print('signal5 emit,value', val)def signal_call_6(self, val, text):print('signal6 emit,value', val, text)def signal_call_7(self, val):print('signal6 overload emit', val)

连接信号 与 槽函数

#信号与槽函数的链接
self.signal1.connect(self.signal_call_1)
self.signal2.connect(self.signal_call_2)
self.signal3.connect(self.signal_call_3)
self.signal4.connect(self.signal_call_4)
self.signal5.connect(self.signal_call_5)
self.signal6[int,str].connect(self.signal_call_6)
self.signal6[str].connect(self.signal_call_7)

发射信号

#信号发射
self.signal1.emit()
self.signal2.emit(1)
self.signal3.emit(1,'第三个')
self.signal4.emit([1,2,3,4])
self.signal5.emit({"name":'JIA','age':'21'})
self.signal6[int,str].emit(1,"第六")
self.signal6[str].emit('第六')

实例:完整代码如下

# -*- coding: utf-8 -*-import sys
from PySide6.QtWidgets import *
from PySide6.QtCore import QObject, Signal, Slotclass CustomSignal(QObject):signal1 = Signal()     # 无参数的信号signal2 = Signal(int)  # 带一个参数(整数)的信号signal3 = Signal(int, str)  # 带两个参数(整数,字符串)的信号signal4 = Signal(list)  # 带一个参数(列表)的信号signal5 = Signal(dict)  # 带一个参数(字典)的信号signal6 = Signal([int, str], [str])  # 带(整数 字符串)或者(字符串)的信号def __init__(self, parent=None):super(CustomSignal, self).__init__(parent)# 信号与槽函数的链接self.signal1.connect(self.signal_call_1)self.signal2.connect(self.signal_call_2)self.signal3.connect(self.signal_call_3)self.signal4.connect(self.signal_call_4)self.signal5.connect(self.signal_call_5)self.signal6[int, str].connect(self.signal_call_6)self.signal6[str].connect(self.signal_call_7)# 信号发射self.signal1.emit()self.signal2.emit(1)self.signal3.emit(1, '第三个')self.signal4.emit([1, 2, 3, 4])self.signal5.emit({"name": 'JIA', 'age': '21'})self.signal6[int, str].emit(1, "第六")self.signal6[str].emit('第六')# 槽函数def signal_call_1(self):print("signal1 emit")def signal_call_2(self, val):print('signal2 emit,value:', val)def signal_call_3(self, val, text):print('signall3 emit,value:', val, text)def signal_call_4(self, val):print('signal4 emit,value:', val)def signal_call_5(self, val):print('signal5 emit,value', val)def signal_call_6(self, val, text):print('signal6 emit,value', val, text)def signal_call_7(self, val):print('signal6 overload emit', val)if __name__ == '__main__':custom_signal = CustomSignal()

自定义参数的传递

在编程过程中,经常会遇到给槽函数传递自定义参数的情况,比如有一个信号与槽函数的连接是

button.clicked.connect(show_page)

对于clicked 信号,它是没有参数的,对于show_page函数来说,希望他可以接受参数,希望show_page 函数如下这样

def show_page(self,name):print(name',点击了’)

于是就会产生一个问题,信号发出的参数个数与槽函数接受的参数个数不一,那么如何解决这个问题呢 ? 这里提供两种解决方法;

  • 第一种:lamdba表达式
  • 第二种:使用functools中的partial函数

两种方法,下面均已写上,自己可运行查看,注意注释。

# -*- coding: utf-8 -*-import sys
from PySide6.QtWidgets import *
from PySide6.QtCore import QObject, Signal, Slot
from functools import partialclass WinForm(QMainWindow):def __init__(self, parent=None):super(WinForm, self).__init__(parent)# 实例化两个按钮button1 = QPushButton('Button1')button2 = QPushButton('Button2')# todo 第一种方法# 单击信号关联槽函数,利用 lambda 表达式传递一个参数# button1.clicked.connect(lambda :self.onButtonClick(1))# button2.clicked.connect(lambda :self.onButtonClick(2))## todo 第二种方法button1.clicked.connect(partial(self.btn_click, 1))button2.clicked.connect(partial(self.btn_click, 2))# 实例化窗口main = QWidget()# 设置窗口的布局,并向其中添加控件layout = QHBoxLayout(main)layout.addWidget(button1)layout.addWidget(button2)# 设置为中央控件self.setCentralWidget(main)self.resize(500, 500)def btn_click(self, n):# 弹窗信息提示框,输出被点击的信息print("Button {0}".format(n))QMessageBox.information(self, '信息提示框', 'Button {0}'.format(n))if __name__ == '__main__':app = QApplication(sys.argv)form = WinForm()form.show()sys.exit(app.exec_())

使用 lambda 表达式传递按钮数字给槽函数,当然还可以传递其他东西,甚至是按钮本身

button1.clicked.connect(lambda :self.onButtonClick(1))
button2.clicked.connect(lambda :self.onButtonClick(2))

使用 functools 中的 partial 函数可以固定函数参数

button1.clicked.connect(partial(self.onButtonClick, 1))
button2.clicked.connect(partial(self.onButtonClick, 2))

装饰器信号与槽

所谓装饰器信号与槽,就是通过装饰器的方法来定义信号与槽函数。

如下

@PySide6.QtCore.Slot(参数)
def on_发送者对象名称)发射信号名称(self,参数):pass

这种方法有效的前提是下面的函数已经执行:

QMetaObject.connectSlotsByName(QObject)

在上面的代码中,"发送者对象名称" 就是使用 "setObjectName函数" 设置的名称。因此自定义槽函数的命名规则也可以看做:

on + 使用setObjectName 设置的名称 + 信号名称

具体实例

# -*- coding: utf-8 -*-import sys
from PySide6.QtWidgets import *
from PySide6.QtCore import QObject, Signal, Slot, QMetaObjectclass WinForm(QWidget):def __init__(self, parent=None):super(WinForm, self).__init__(parent)self.btn_ok = QPushButton('ok', self)  # 创建按钮,添加到自身窗口中self.btn_ok.setObjectName('btn_ok')  # 使用 setObjectName 设置对象名称# 设置自身的布局为水平布局,并添加按钮控件到其中layout = QHBoxLayout(self)layout.addWidget(self.btn_ok)self.resize(300, 150)# TODo 第一种方法# self.okButton.clicked.connect(self.btn_ok_clicked)# 第二种方法QMetaObject.connectSlotsByName(self)# def btn_ok_clicked(self):#     print('单击了ok按钮')@Slot()def on_btn_ok_clicked(self):print('单击了ok按钮')if __name__ == '__main__':app = QApplication(sys.argv)form = WinForm()form.show()sys.exit(app.exec())

QtCore.QMetaObject.connectSlotsByName(self) 是 PySide6 中根据 信号名称自动连接到槽函数的核心代码,这行代码用来将 QObject 中的子孙对象的某些对象按照其 objectName 连接到相应的槽函数。

举个例子说名一下,假设代码 QtCore.QMetaObject.connectSlotsByName(self) 已经执行,则下面的代码

@QtCore.Slot()
def on_okButton_clicked(self):print('单击了ok按钮')

会被自动识别为下面的代码

def __init__(self,parent=None):self.okButton.clicked.connect(self.okButton_clicked)def okButton_clicked(self):print('单击了ok按钮')

信号与槽的断开与连接

有时候基于某些原因,想要临时或永久的断开某个信号与槽函数的连接,一般把 connect 前面加上dis 就是解除绑定的意思:即disconnect

实例如下

# -*- coding: utf-8 -*-import sys
from PySide6.QtWidgets import *
from PySide6.QtCore import QObject, Signal, Slot, QMetaObjectclass SignalClass(QObject):signal1 = Signal()     # 声明无参数的信号signal2 = Signal(int)  # 声明带一个int类型参数的信号def __init__(self, parent=None):super(SignalClass, self).__init__(parent)# 将 signal1 信号连接到两个槽函数self.signal1.connect(self.sig1Call)self.signal1.connect(self.sig2Call)# 将signal2信号连接到信号1self.signal2.connect(self.signal1)# 发射信号self.signal1.emit()self.signal2.emit(1)# 断开信号与槽函数的关系self.signal1.disconnect(self.sig1Call)self.signal1.disconnect(self.sig2Call)self.signal2.disconnect(self.signal1)# 绑定信号与槽函数self.signal1.connect(self.sig1Call)self.signal2.connect(self.sig1Call)# 信号发射self.signal1.emit()self.signal2.emit(1)# 输出信号1发射def sig1Call(self):print('signal-1 emit')# 输出信号2发射def sig2Call(self):print('signal-2 emit')if __name__ == '__main__':signal = SignalClass()

4、信号 与 槽 之 Qt Designer 神助攻

前面都是手工输入代码的信号与槽的使用方法,因为采用这种方法介绍时会简单一些。但是在实战应用中,由于 Qt Designer 可以很好的实现界面显示与业务逻辑分离,如果能够使用 Qt Designer 自动创建一些信号与槽机制,那就更好了

本例要实现的功能是:通过一个模拟打印的界面来详细说明信号的使用,在打印时,可以设置打印的份数,纸张类型,触发打印按钮后,将执行结果显示在右侧,通过QCheckBox(全屏预览 复选框)来选择是否通过全屏模式进行预览,将执行结果显示在右侧
按F1键可以显示helpmessage帮助信息

第一步:Qt Designer

首先,使用Qt Designer新建一个模板名为widget的简单窗口,通过将widget box区域的控件拖曳到窗口中,实现如图的界面效果

这里对窗口控件进行简要说明

控件类型控件名称作用
QSpinBoxnumberSpinBox显示打印的分数
QComboBoxstyleCombo显示打印的纸张类型,纸张类型包括A3,A4等
QPushButtonprintButton连接emitPrintSiagnal函数的绑定,触发自定义信号printSignal的发射
QCheckBoxprievewState是否全屏预览
QPushButtonpriviewButton连接emitPreviewSignal函数的绑定,触发自定义信号previewSignal的发射
QLabelresultLabel显示执行结果

第二步:将界面文件ui转换为py文件

pyuic5 -o xxxxx.py xxxxx.ui

会在界面文件同级目录下生成一个py文件,为了使窗口的显示与业务逻辑分离,在建一个调用窗口显示的文件,在调用类中添加多个自定义信号,并与槽函数进行绑定,其完整代码如下

# -*- coding: utf-8 -*-import sys
from PySide6 import QtCore, QtGui, QtWidgets
from PySide6.QtWidgets import *class Ui_MainWindow(object):def setupUi(self, MainWindow):MainWindow.setObjectName("Form")MainWindow.resize(715, 225)self.controlsGroup = QtWidgets.QGroupBox(MainWindow)self.controlsGroup.setGeometry(QtCore.QRect(10, 20, 451, 151))self.controlsGroup.setObjectName("controlsGroup")self.widget = QtWidgets.QWidget(self.controlsGroup)self.widget.setGeometry(QtCore.QRect(10, 40, 411, 30))self.widget.setObjectName("widget")self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget)self.horizontalLayout.setContentsMargins(0, 0, 0, 0)self.horizontalLayout.setObjectName("horizontalLayout")self.label = QtWidgets.QLabel(self.widget)self.label.setObjectName("label")self.horizontalLayout.addWidget(self.label)self.numberSpinBox = QtWidgets.QSpinBox(self.widget)self.numberSpinBox.setObjectName("numberSpinBox")self.horizontalLayout.addWidget(self.numberSpinBox)self.styleCombo = QtWidgets.QComboBox(self.widget)self.styleCombo.setObjectName("styleCombo")self.styleCombo.addItem("")self.styleCombo.addItem("")self.styleCombo.addItem("")self.horizontalLayout.addWidget(self.styleCombo)self.label_2 = QtWidgets.QLabel(self.widget)self.label_2.setObjectName("label_2")self.horizontalLayout.addWidget(self.label_2)self.printButton = QtWidgets.QPushButton(self.widget)self.printButton.setObjectName("printButton")self.horizontalLayout.addWidget(self.printButton)self.widget1 = QtWidgets.QWidget(self.controlsGroup)self.widget1.setGeometry(QtCore.QRect(10, 100, 201, 30))self.widget1.setObjectName("widget1")self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.widget1)self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)self.horizontalLayout_2.setObjectName("horizontalLayout_2")self.previewStatus = QtWidgets.QCheckBox(self.widget1)self.previewStatus.setObjectName("previewStatus")self.horizontalLayout_2.addWidget(self.previewStatus)self.previewButton = QtWidgets.QPushButton(self.widget1)self.previewButton.setObjectName("previewButton")self.horizontalLayout_2.addWidget(self.previewButton)self.resultGroup = QtWidgets.QGroupBox(MainWindow)self.resultGroup.setGeometry(QtCore.QRect(470, 20, 231, 151))self.resultGroup.setObjectName("resultGroup")self.resultLabel = QtWidgets.QLabel(self.resultGroup)self.resultLabel.setGeometry(QtCore.QRect(20, 30, 191, 101))self.resultLabel.setObjectName("resultLabel")self.retranslateUi(MainWindow)QtCore.QMetaObject.connectSlotsByName(MainWindow)def retranslateUi(self, MainWindow):_translate = QtCore.QCoreApplication.translateMainWindow.setWindowTitle(_translate("Form", "打印控件"))self.controlsGroup.setTitle(_translate("Form", "打印控制"))self.label.setText(_translate("Form", "打印份数:"))self.styleCombo.setItemText(0, _translate("Form", "A3"))self.styleCombo.setItemText(1, _translate("Form", "A4"))self.styleCombo.setItemText(2, _translate("Form", "A5"))self.label_2.setText(_translate("Form", "纸张类型:"))self.printButton.setText(_translate("Form", "打印"))self.previewStatus.setText(_translate("Form", "全屏预览"))self.previewButton.setText(_translate("Form", "预览"))self.resultGroup.setTitle(_translate("Form", "操作结果"))self.resultLabel.setText(_translate("Form", "<html><head/><body><p><br/></p></body></html>"))class MyMainWindow(QMainWindow, Ui_MainWindow):help_signal = QtCore.Signal(str)print_signal = QtCore.Signal(list)# 声明一个多重载版本的信号,包括了一个带int和str类型参数的信号,以及带str参数的信号preview_signal = QtCore.Signal([int, str], [str])def __init__(self, parent=None):super(MyMainWindow, self).__init__(parent)self.setupUi(self)self.init_signal_and_slot()def init_signal_and_slot(self):self.help_signal.connect(self.show_help_message)self.print_signal.connect(self.print_paper)self.preview_signal[str].connect(self.preview_paper)self.preview_signal[int, str].connect(self.preview_paper_with_args)self.printButton.clicked.connect(self.emit_print_signal)self.previewButton.clicked.connect(self.emit_preview_signal)# 发射预览信号def emit_preview_signal(self):if self.previewStatus.isChecked():self.preview_signal[int, str].emit(1080, " Full Screen")elif not self.previewStatus.isChecked():self.preview_signal[str].emit("Preview")# 发射打印信号def emit_print_signal(self):print_info = [self.numberSpinBox.value(), self.styleCombo.currentText()]self.print_signal.emit(print_info)def print_paper(self, print_info):self.resultLabel.setText("打印: " + "份数:" + str(print_info[0]) + " 纸张:" + str(print_info[1]))def preview_paper_with_args(self, style, text):self.resultLabel.setText(str(style) + text)def preview_paper(self, text):self.resultLabel.setText(text)# 重载点击键盘事件def keyPressEvent(self, event):if event.key() == QtCore.Qt.Key_F1:self.help_signal.emit("help message")# 显示帮助消息def show_help_message(self, message):self.resultLabel.setText(message)self.statusBar().showMessage(message)if __name__ == "__main__":app = QApplication(sys.argv)win = MyMainWindow()win.show()sys.exit(app.exec())

5、多线程中信号与槽的使用

最简单的多线程 QThread 使用

方法是利用 QThread 函数。

示例:QThread 函数和信号简单结合的方法

# -*- coding: utf-8 -*-import sys
from PySide6.QtCore import *
from PySide6.QtWidgets import *class MyThread(QThread):# 自定义信号参数为str类型custom_signal = Signal(str)def __init__(self, parent=None):super(MyThread, self).__init__(parent)# 初始化名称为空self.times = Noneself.identity = Nonedef set_identity(self, text):# 设置多线程名称self.identity = textdef set_val(self, val):# 接受数据,运行多线程self.times = int(val)self.run()def run(self):# 当次数大于0以及名称不为空时执行代码while self.times > 0 and self.identity:# 发射信号,触发打印函数,次数-1self.custom_signal.emit(self.identity + '==>' + str(self.times))self.times -= 1class WinForm(QWidget):def __init__(self, parent=None):super(WinForm, self).__init__(parent)# 创建一个线程实例并设置名称 变量 信号与槽self.thread = MyThread()self.thread.set_identity('thread1')self.thread.custom_signal.connect(self.out_text)self.thread.set_val(6)# 打印输出文本def out_text(self, text):print(text)if __name__ == '__main__':app = QApplication(sys.argv)form = WinForm()form.show()sys.exit(app.exec())pass

示例:

import sys, time
from PySide6.QtCore import (Signal, Slot, Qt, QThread
)
from PySide6.QtWidgets import (QWidget, QVBoxLayout, QPushButton, QLabel, QApplication
)class mainWindow(QWidget):def __init__(self) -> None:super().__init__()self.label = QLabel("Hello!")self.label.setAlignment(Qt.AlignCenter)self.but = QPushButton("Click!")self.but.clicked.connect(self.fun)self.layout = QVBoxLayout()self.layout.addWidget(self.label)self.layout.addWidget(self.but)self.setLayout(self.layout)self.setWindowTitle('Signal Example')self.resize(300, 300)self.show()@Slot()def fun(self):self.th = Th()self.th.timer.connect(self.flushlabel)self.th.finish.connect(self.isFinish)self.th.start()@Slot(int)def flushlabel(self, nu):self.label.setText(str(nu))@Slot(bool)def isFinish(self, bo):if bo is True:self.but.setEnabled(True)else:self.but.setEnabled(False)class Th(QThread):timer = Signal(int)finish = Signal(bool)def __init__(self) -> None:super().__init__()def run(self):print('Start Timer')self.finish.emit(False)for x in range(5):self.timer.emit(5 - x)time.sleep(1)self.finish.emit(True)if __name__ == '__main__':app = QApplication([])widgets = mainWindow()sys.exit(app.exec())

主线程与子线程的使用

有时候在开发程序时会经常执行一些耗时的操作,这样就会导致界面卡顿,这也是多线程的应用范围之一,这样我们就可以创建多线程,使用主线程更新界面,使用子线程后台处理数据,最后将结果显示在界面上

# -*- coding: utf-8 -*-import sys
import time
from PySide6.QtCore import *
from PySide6.QtWidgets import *class BackQthread(QThread):# 自定义信号为str参数类型update_date = Signal(str)def run(self):while True:# 获得当前系统时间data = QDateTime.currentDateTime()# 设置时间显示格式current_time = data.toString('yyyy-MM-dd hh:mm:ss dddd')# 发射信号self.update_date.emit(str(current_time))# 睡眠一秒time.sleep(1)class window(QDialog):def __init__(self):super(window, self).__init__()# 设置标题与初始大小self.backend = Noneself.setWindowTitle('PyQt5界面实时更新的例子')self.resize(400, 100)# 实例化文本输入框及其初始大小self.input = QLineEdit(self)self.input.resize(400, 100)self.init_ui()def init_ui(self):# 实例化对象self.backend = BackQthread()# 信号连接到界面显示槽函数self.backend.update_date.connect(self.handle_display)# 多线程开始self.backend.start()def handle_display(self, data):# 设置单行文本框的文本self.input.setText(data)if __name__ == '__main__':app = QApplication(sys.argv)win = window()win.show()sys.exit(app.exec())

6、信号与槽之多窗口数据传递

在pyqt编程过程中,经常会遇到输入或选择多个参数的问题,把多个参数写到一个窗口中,主窗口会显得很臃肿,所以,一般是添加一个按钮,调用对话框,在对话框中进行参数的选择,关闭对话框将参数返回给主窗口
pyqt提供了一些标准的对话框类,用于输入数据,修改数据,更改应用的设置等,常见的有QFileDialog,QInputDialog,QColorDialog, QFontDialog等,在不同的窗口之间传参数有两种常用的方式,一种在自定义对话框之间通过属性传参,另一种在窗口之间使用信号与槽

示例 1:单一窗口的数据传递

对于具有单一窗口的程序来说,一个控件的变化会影响另一个控件的变化,这中变化利用信号与槽的关系非常容易解决

# -*- coding: utf-8 -*-import sys
import time
from PySide6.QtCore import *
from PySide6.QtWidgets import *class WinForm(QWidget):def __init__(self):super(WinForm, self).__init__()self.init_ui()def init_ui(self):# 先创建水平滑块和Lcd控件lcd = QLCDNumber(self)slider = QSlider(Qt.Horizontal, self)# 垂直布局,添加控件vbox = QVBoxLayout()vbox.addWidget(lcd)vbox.addWidget(slider)# 设置窗口布局self.setLayout(vbox)# 设置滑块数值信号改变连接Lcd的更新slider.valueChanged.connect(lcd.display)# 设置初始位置以及初始大小,设置标题self.setGeometry(300, 300, 350, 150)self.setWindowTitle('信号与槽:连接滑块LCd')if __name__ == '__main__':app = QApplication(sys.argv)form = WinForm()form.show()sys.exit(app.exec())

示例 2:多窗口数据传递:调用属性

新建对话框子窗口属性,form_QDialog.py

import sys
import time
from PySide6.QtCore import *
from PySide6.QtWidgets import *class DateDialog(QDialog):def __init__(self, parent=None):super(DateDialog, self).__init__(parent)self.setWindowTitle('DateDialog')# 在布局中添加控件layout = QVBoxLayout(self)self.datetime = QDateTimeEdit(self)self.datetime.setCalendarPopup(True)self.datetime.setDateTime(QDateTime.currentDateTime())layout.addWidget(self.datetime)buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)buttons.accepted.connect(self.accept)buttons.rejected.connect(self.reject)layout.addWidget(buttons)def date_time(self):return self.datetime.dateTime()@staticmethoddef get_datetime(parent=None):dialog = DateDialog(parent)result = dialog.exec_()date = dialog.date_time()return date.date(), date.time(), result == QDialog.Accepted

再新建一个主窗口文件 form_main.py ,用来调用 form_QDialog.py

# -*- coding: utf-8 -*-
# @Author  : 佛祖保佑, 永无 bug
# @Date    : 
# @File    : form_main.py.py
# @Software: PyCharm
# @description : XXXimport sys
from PySide6.QtWidgets import *
from form_QDialog import DateDialogclass WinForm(QWidget):def __init__(self, parent=None):super(WinForm, self).__init__(parent)self.resize(400, 90)self.setWindowTitle('对话框关闭时返回值给主窗口的例子')self.lineEdit = QLineEdit(self)self.btn1 = QPushButton('弹出对话框1')self.btn1.clicked.connect(self.on_btn1_clicked)self.btn2 = QPushButton('弹出对话框2')self.btn2.clicked.connect(self.on_btn2_clicked)grid_layout = QGridLayout(self)grid_layout.addWidget(self.lineEdit)grid_layout.addWidget(self.btn1)grid_layout.addWidget(self.btn2)def on_btn1_clicked(self):dialog = DateDialog(self)result = dialog.exec()date = dialog.date_time()self.lineEdit.setText(date.date().toString())print('\n日期对话框的返回值')print('date=%s' % str(date.date))print('time=%s' % str(date.time()))print('result=%s' % result)def on_btn2_clicked(self):date, time, result = DateDialog.get_datetime()self.lineEdit.setText(date.toString())print('\n 日期对话框的返回值')print('date=%s' % str(date))print('time=%s' % str(time))print('result=%s' % result)if __name__ == '__main__':app = QApplication(sys.argv)form = WinForm()form.show()sys.exit(app.exec())pass

运行结果:

示例 3:多窗口数据传递:信号与槽

对于多窗口的数据传递,一般是通过子窗口发射信号的,主窗口通过槽函数捕获这个信号,然后获取信号里面的数据。

子窗口发射的信号有两种:

  • 一种是发射内置pyqt信号。
  • 一种是发射自定义的信号。发射自定义的信号的好处是它的参数可以自定义,可以为int list dict等各种类型与多个参数

建一个子对话框文件,这里名称为:form_QDialog.py

# -*- coding: utf-8 -*-from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *class DateDialog(QDialog):Signal_OneParameter = Signal(str)def __init__(self, parent=None):super(DateDialog, self).__init__(parent)self.setWindowTitle('子窗口:用来发射信号')# 在布局中添加部件layout = QVBoxLayout(self)self.label = QLabel(self)self.label.setText('前者发射内置信号\n后者发射自定义信号')self.datetime_inner = QDateTimeEdit(self)self.datetime_inner.setCalendarPopup(True)self.datetime_inner.setDateTime(QDateTime.currentDateTime())self.datetime_emit = QDateTimeEdit(self)self.datetime_emit.setCalendarPopup(True)self.datetime_emit.setDateTime(QDateTime.currentDateTime())layout.addWidget(self.label)layout.addWidget(self.datetime_inner)layout.addWidget(self.datetime_emit)# 使用两个button(ok和cancel)分别连接accept()和reject()槽函数buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel,Qt.Horizontal, self)buttons.accepted.connect(self.accept)buttons.rejected.connect(self.reject)layout.addWidget(buttons)self.datetime_emit.dateTimeChanged.connect(self.emit_signal)def emit_signal(self):date_str = self.datetime_emit.dateTime().toString()self.Signal_OneParameter.emit(date_str)

创建主窗口 form_main.py,调用对话框文件 form_QDialog.py


import sys
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
from form_QDialog import DateDialogclass WinForm(QWidget):def __init__(self, parent=None):super(WinForm, self).__init__(parent)self.resize(400, 90)self.setWindowTitle('信号与槽传递参数的示例')self.open_btn = QPushButton('获取时间')self.lineEdit_inner = QLineEdit(self)self.lineEdit_emit = QLineEdit(self)self.open_btn.clicked.connect(self.open_dialog)self.lineEdit_inner.setText('接收子窗口内置信号的时间')self.lineEdit_emit.setText('接收子窗口自定义信号的时间')grid = QGridLayout()grid.addWidget(self.lineEdit_inner)grid.addWidget(self.lineEdit_emit)grid.addWidget(self.open_btn)self.setLayout(grid)def open_dialog(self):dialog = DateDialog(self)'''连接子窗口的内置信号与主窗口的槽函数'''dialog.datetime_inner.dateTimeChanged.connect(self.deal_inner_slot)'''连接子窗口的自定义信号与主窗口的槽函数'''dialog.Signal_OneParameter.connect(self.deal_emit_slot)dialog.show()def deal_inner_slot(self, date):self.lineEdit_inner.setText(date.toString())def deal_emit_slot(self, date_str):self.lineEdit_emit.setText(date_str)if __name__ == "__main__":app = QApplication(sys.argv)form = WinForm()form.show()sys.exit(app.exec())

7、信号与槽 之 事件处理机制

信号与槽可以说是对事件处理机制的高级封装,如果说事件是用来创建窗口控件的,那么信号与槽就是用来对这个控件进行使用的,比如一个按钮,当我们使用按钮时,只关心clicked信号,至于这个按钮如何接受并处里鼠标点击事件,然后再发射这个信号,则不关心,但是如果要重载一个按钮,这时候就要关心了,比如可以改变它的行为:在鼠标按下时触发 clicked 信号,而不是释放时

常见事件类型

qt 程序是事件驱动的,它的每个动作都有幕后某个事件所触发,Qt事件类型有很多,常见的如下

  • 键盘事件:按键的按下与松开
  • 鼠标事件:鼠标指针的移动,鼠标按键的按下与松开
  • 拖放事件:用鼠标进行拖放
  • 滚轮事件:鼠标滚轮滚动
  • 绘屏事件:重绘制屏幕的某些部分
  • 定时事件:定时器到时
  • 焦点事件:键盘焦点移动
  • 进入和离开事件:鼠标指针移入Widget内,或者移出
  • 移动事件:Widget的位置改变
  • 大小改变事件:widget的大小改变
  • 显示和隐藏事件:widget显示与隐藏
  • 窗口事件:窗口是否为当前窗口

还有一些常见的 qt 事件,比如 Socket 事件,剪切板事件,字体改变事件,布局改变事件

使用事件处理的方法

pyqt 提供如下 5 种事件处理和过滤的方法(有弱到强),其中只有前两种方法使用最频繁

1. 重新实现事件函数

比如 mousePressEvent(),keyPressEvent(),paintEvent(),这是最常规的事件处理方法

2. 重新实现 QObject.event()

一般用在pyqt没有提供该事件的处理函数的情况下,即增加新事件时

3. 安装事件过滤器

如果对QObject调用installEventFilter,则相当于为这个QObject安装了一个事件过滤器,对于QObject的全部事件来说,它们都会先传递到事件过滤函数eventFilter中,在这个函数中,我们可以抛弃或者修改这些事件,比如对自己感兴趣的事件使用自定义的处理机制,对其他事件采用默认的事件处理机制,由于这中方法会调用installEventFilter的所有QObject的事件进行过滤,因此如果要过滤的事件比较多,则会降低程序的性能

4. 在 QApplication 中安装事件过滤器

这种方法比上一种更强大,QApplication的事件过滤器将捕获所有的QObject事件,而且第一个获得该事件,也就是说,在将事件发送给其他任何一个事件过滤器之前,都会发送给QApplication的事件过滤器

5. 重新实现QApplication的notify()方法

pyqt使用notify来分发事件,要想在任何事件处理器之前捕获事件,唯一的方法就是重新实现QApplication的notify(),在实践中,在调试才会用这中方法

示例:经典案例

绘制事件

调整窗口大小事件

鼠标释放事

鼠标移动事件

键盘按下事件

重载tab键

import sys
from PySide6.QtCore import (QEvent, QTimer, Qt)
from PySide6.QtWidgets import (QApplication, QMenu, QWidget)
from PySide6.QtGui import QPainterclass Widget(QWidget):def __init__(self, parent=None):super(Widget, self).__init__(parent)# 初始化数据# 鼠标双击Falseself.justDoubleClicked = False# 按键,输出文本,提示消息为空self.key = ""self.text = ""self.message = ""# 设置窗口初始大小与位置self.resize(400, 300)self.move(100, 100)# 设置标题self.setWindowTitle("Events")# 定时器1秒后执行槽函数QTimer.singleShot(1000, self.give_help)# 避免窗口大小重绘事件的影响,可以把参数0改变成3000(3秒),然后在运行,就可以明白这行代码的意思。def give_help(self):self.text = "请点击这里触发追踪鼠标功能"# 重绘事件,也就是触发paintEvent函数。self.update()'''重新实现关闭事件'''def closeEvent(self, event):print("Closed")'''重新实现上下文菜单事件'''def contextMenuEvent(self, event):# 实例化菜单,添加子菜单one two并附加快捷键功能,关联槽函数menu = QMenu(self)one_action = menu.addAction("&One")two_action = menu.addAction("&Two")one_action.triggered.connect(self.one)two_action.triggered.connect(self.two)# 如果message为空,执行if not self.message:# 在菜单中添加一条分割线menu.addSeparator()# 添加自菜单three,关联槽函数threeAction = menu.addAction("Thre&e")threeAction.triggered.connect(self.three)# 菜单栏出现在鼠标的位置menu.exec_(event.globalPos())'''上下文菜单槽函数'''def one(self):self.message = "Menu option One"self.update()def two(self):self.message = "Menu option Two"self.update()def three(self):self.message = "Menu option Three"self.update()'''重新实现绘制事件'''def paintEvent(self, event):text = self.texti = text.find("\n\n")if i >= 0:text = text[0:i]# 若触发了键盘按钮,则在文本信息中记录这个按钮信息。if self.key:text += "\n\n你按下了: {0}".format(self.key)painter = QPainter(self)painter.setRenderHint(QPainter.TextAntialiasing)# 绘制信息文本的内容painter.drawText(self.rect(), Qt.AlignCenter, text)# 若消息文本存在则在底部居中绘制消息,5秒钟后清空消息文本并重绘。if self.message:# 显示给定坐标处的文本,坐标,对齐方式。文本内容painter.drawText(self.rect(), Qt.AlignBottom | Qt.AlignHCenter,self.message)# 5秒钟后触发清空信息的函数,并重新绘制事件QTimer.singleShot(5000, self.clear_message)QTimer.singleShot(5000, self.update)'''清空消息文本的槽函数'''def clear_message(self):self.message = ""'''重新实现调整窗口大小事件'''def resizeEvent(self, event):self.text = "调整窗口大小为: QSize({0}, {1})".format(event.size().width(), event.size().height())self.update()'''重新实现鼠标释放事件'''def mouseReleaseEvent(self, event):# 若鼠标释放为双击释放,则不跟踪鼠标移动if self.justDoubleClicked:self.justDoubleClicked = False# 若鼠标释放为单击释放,则需要改变跟踪功能的状态,如果开启跟踪功能的话就跟踪,不开启跟踪功能就不跟踪else:# 单击鼠标self.setMouseTracking(not self.hasMouseTracking())if self.hasMouseTracking():self.text = "开启鼠标跟踪功能.\n" + \"请移动一下鼠标!\n" + \"单击鼠标可以关闭这个功能"else:self.text = "关闭鼠标跟踪功能.\n" + \"单击鼠标可以开启这个功能"self.update()'''重新实现鼠标移动事件'''def mouseMoveEvent(self, event):# 如果没有鼠标双击,执行if not self.justDoubleClicked:# 窗口坐标转换为屏幕坐标global_pos = self.mapToGlobal(event.pos())self.text = """鼠标位置:窗口坐标为:QPoint({0}, {1}) 屏幕坐标为:QPoint({2}, {3}) """.format(event.pos().x(), event.pos().y(), global_pos.x(), global_pos.y())self.update()'''重新实现鼠标双击事件'''def mouseDoubleClickEvent(self, event):self.justDoubleClicked = Trueself.text = "你双击了鼠标"self.update()'''重新实现键盘按下事件'''def keyPressEvent(self, event):self.key = ""if event.key() == Qt.Key_Home:self.key = "Home"elif event.key() == Qt.Key_End:self.key = "End"elif event.key() == Qt.Key_PageUp:if event.modifiers() & Qt.ControlModifier:self.key = "Ctrl+PageUp"else:self.key = "PageUp"elif event.key() == Qt.Key_PageDown:if event.modifiers() & Qt.ControlModifier:self.key = "Ctrl+PageDown"else:self.key = "PageDown"elif Qt.Key_A <= event.key() <= Qt.Key_Z:if event.modifiers() & Qt.ShiftModifier:self.key = "Shift+"self.key += event.text()# 如果key有字符,不为空,则绘制字符if self.key:self.key = self.keyself.update()# 否则就继续监视这个事件else:QWidget.keyPressEvent(self, event)'''重新实现其他事件,适用于PyQt没有提供该事件的处理函数的情况,Tab键由于涉及焦点切换,不会传递给keyPressEvent,因此,需要在这里重新定义。'''def event(self, event):# 如果有按键按下,并且按键是tab键if (event.type() == QEvent.KeyPress andevent.key() == Qt.Key_Tab):self.key = "在event()中捕获Tab键"self.update()return Truereturn QWidget.event(self, event)if __name__ == "__main__":app = QApplication(sys.argv)form = Widget()form.show()app.exec()

示例 2:过滤器的使用

下面的代码意思是这个过滤器只对 label1 的事件进行处理,并且只处理它的鼠标按下事件和鼠标释放事件

import sysfrom PySide6.QtGui import *
from PySide6.QtCore import *
from PySide6.QtWidgets import *class EventFilter(QDialog):def __init__(self, parent=None):super(EventFilter, self).__init__(parent)self.setWindowTitle('事件过滤器')# 实例化并设置四个标签文本self.label1 = QLabel('请点击')self.label2 = QLabel('请点击')self.label3 = QLabel('请点击')self.labelState = QLabel('test')# 加载三个图片self.image1 = QImage('images\cartoon1.ico')self.image2 = QImage('images\cartoon2.ico')self.image3 = QImage('images\cartoon3.ico')self.width = 600self.height = 300# 设置初始大小self.resize(self.width, self.height)# 使用事假过滤器self.label1.installEventFilter(self)self.label2.installEventFilter(self)self.label3.installEventFilter(self)# 设置窗口布局方式并添加控件layout = QGridLayout(self)layout.addWidget(self.label1, 500, 0)layout.addWidget(self.label2, 500, 1)layout.addWidget(self.label3, 500, 2)layout.addWidget(self.labelState, 600, 1)def eventFilter(self, watched, event):# 对事件一的处理过滤机制if watched == self.label1:if event.type() == QEvent.MouseButtonPress:mouseEvent = QMouseEvent(event)if mouseEvent.buttons() == Qt.LeftButton:self.labelState.setText('按下鼠标左键')elif mouseEvent.buttons() == Qt.MidButton:self.labelState.setText('按下鼠标中间键')elif mouseEvent.buttons() == Qt.RightButton:self.labelState.setText('按下鼠标右键')# 转换图片大小transform = QTransform()transform.scale(0.5, 0.5)tmp = self.image1.transformed(transform)self.label1.setPixmap(QPixmap.fromImage(tmp))if event.type() == QEvent.MouseButtonRelease:self.labelState.setText('释放鼠标按键')self.label1.setPixmap(QPixmap.fromImage(self.image1))return QDialog.eventFilter(self, watched, event)if __name__ == '__main__':app = QApplication(sys.argv)dialog = EventFilter()app.installEventFilter(dialog)dialog.show()app.exec()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/495090.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

芯片业又起波澜!博通189亿美元收购遭质疑,股价一度跌近19%

来源&#xff1a;华尔街见闻摘要&#xff1a;如果说博通上次收购高通面临的最大“对手”是特朗普政府&#xff0c;这次收购CA的“对手”可能是华尔街。如果说博通上次收购高通面临的最大“对手”是特朗普政府&#xff0c;这次收购CA的“对手”可能是华尔街。美东时间周三&#…

JavaScript常用技巧专题五

文章目录 一、使用适当的命名和注释来提高代码可读性二、优雅的写条件判断代码2.1、普通的if else2.2、三元运算符2.3、多个if else2.4、switch case2.5、对象写法2.6、Map写法 三、封装条件语句四、函数应该只做一件事五、Object.assign给默认对象赋默认值六、函数参数两个以下…

HTML 页面的生命周期、HTML 事件

From&#xff1a;https://blog.csdn.net/WuLex/article/details/101016936 1、页面生命周期 HTML页面的生命周期有以下三个重要事件&#xff0c;每个事件都有特定的用途 DOMContentLoaded &#xff1a; 浏览器已经完全加载 HTML&#xff0c;DOM 树已经构建完毕&#xff0c;js …

腾讯再次海选AI项目,1500进40,医疗零售机器人成新风向

雷刚 发自 凹非寺 量子位 报道 | 公众号 QbitAI一年一度风向标&#xff0c;腾讯又一次海选AI项目。去年第一期腾讯AI加速器结业后&#xff0c;鹅厂就马不停蹄开启了第二期报名&#xff0c;而且这一次报名企业更多、竞争更激烈、最终录取概率甚至不到3%。第二期AI加速器通过初试…

The Human Touch 将人工智能和机器人用于病人工作的实际和伦理意义

来源&#xff1a;IEEE电气电子工程师学会摘要&#xff1a;我们生活在一个科幻小说可以很快成为科学事实的时代。在一代人的时间里&#xff0c;互联网已经从技术奇迹变成了实用工具&#xff0c;移动电话重新定义了我们的交流方式。我们生活在一个科幻小说可以很快成为科学事实的…

渗透测试 ( 0 ) --- XSS、CSRF、文件上传、文件包含、反序列化漏洞

漏洞数据库&#xff1a;https://www.exploit-db.com/google-hacking-database 1、渗透测试 实用 浏览器插件 chrome、edge 插件&#xff1a;搜索 cookie&#xff0c;安装 cookie editor&#xff0c;打开插件&#xff0c;可以 导出 cookie HackBar &#xff1a;Hackbar是网络安…

专访盛大创始人陈天桥:未来的杀手级应用必将诞生于脑科学

翻译丨于波 校对丨其奇来源丨Medium 神经科技初见陈天桥&#xff0c;他穿着带有花纹的短袖衬衫&#xff0c;休闲款式的蓝色牛仔裤&#xff0c;迷彩色的运动鞋&#xff0c;仿佛是个享受退休生活的人。过去的他可不是这样。1999年&#xff0c;陈天桥创建盛大游戏公司&#xff0c…

动手解决jar转txt软件的一个缺陷

代码&#xff1a; import java.io.BufferedOutputStream;import java.io.BufferedReader;import java.io.DataOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStreamReade…

渗透测试 ( 2 ) --- 渗透测试系统、靶机、GoogleHacking、kali工具

操作系统&#xff1a;https://zhuanlan.zhihu.com/p/162865015 1、基于 Windows、Linux、Android 的渗透测试系统 1.1 基于 Linux 的系统 Kali&#xff1a;https://www.kali.org/get-kali/Parrot Security OS&#xff1a;Parrot Securitybackbox&#xff1a;https://www.backbo…

清华发布《中国AI发展报告2018》:中科院系统AI论文产出全球第一

来源&#xff1a;大数据文摘人工智能正成为全球性话题&#xff0c;各国的AI人才争夺战也正愈演愈烈。那么目前&#xff0c;人工智能在中国的发展条件如何&#xff0c;中国距离成为真正的人工智能强国到底还有多远&#xff1f;基于此&#xff0c;7月13日&#xff0c;《中国人工智…

单例模式小记【原创】

中国的历史上很少出现两个皇帝并存的时期&#xff0c;是有&#xff0c;但不多&#xff0c;那我们就认为皇帝是个单例模式&#xff0c;在这个场景中&#xff0c;有皇帝&#xff0c;有大臣&#xff0c;大臣是天天要上朝参见皇帝的&#xff0c;今天参拜的皇帝应该和昨天、前天的一…

渗透测试 ( 3 ) --- Metasploit Framework ( MSF )

白嫖 &#xff1a;https://zhuanlan.zhihu.com/p/449836479&#xff1a;http://t.zoukankan.com/hxlinux-p-15787814.html&#xff1a;https://www.52pojie.cn/thread-1586222-1-1.html Metasploit Pro 英文文档&#xff1a;https://docs.rapid7.com/metasploit/ Metasploit P…

工业4.0进行时:工业机器人为何能够快速爆发?

来源&#xff1a;资本实验室摘要&#xff1a;聚焦前沿科技创新与传统产业升级自George Devol于1961发明第一台可编程工业机器人“Unimate”以来&#xff0c;工业机器人产业已经走过了几十年的历史。到了2000年&#xff0c;全球约有74.25万台工业机器人。其中&#xff0c;超过一…

CRITICAL_SECTION 学习

// Critsetion.cpp : 定义控制台应用程序的入口点。 //#include "stdafx.h" #include <Windows.h> #include <iostream> #include <process.h> using namespace std;CRITICAL_SECTION g_cs; char name[]"zhangdongsheng";unsigned __std…

渗透测试 ( 4 ) --- Meterpreter 命令详解

From&#xff1a;https://blog.csdn.net/weixin_45605352/article/details/115824811 <<Web 安全攻防(渗透测试实战指南)>> 1、初识 Meterpreter 1.1.什么是 Meterpreter Meterpreter 是 Metasploit 框架中的一个扩展模块&#xff0c;作为溢出成功以后的攻击载荷使…

深度:中国车企遭遇最大危机!末尾淘汰赛开始【附下载】| 智东西内参

来源&#xff1a;智东西摘要&#xff1a;靠“合资”起步的中国自主品牌汽车走到了成熟期的转折点&#xff0c;面临的形势极为严峻。中国汽车自主品牌30多年的发展过程&#xff0c;从闭门造车到合资建厂&#xff0c;再到民营崛起&#xff0c;正在逐渐走向开放。经国务院批准&…

渗透测试 ( 5 ) --- 扫描之王 nmap、渗透测试工具实战技巧合集

Nmap 官方文档 ( 中文文档是 Nmap 版本4.50&#xff0c;英文文档是最新的 )&#xff1a; 英文文档&#xff1a;https://nmap.org/book/man.html中文文档&#xff1a;https://nmap.org/man/zh/index.html#man-description官方 Nmap 项目指南 &#xff1a;https://nmap.org/book…

OSI、TCP/IP or Five-layer(Protocols Use) Model

转载于:https://www.cnblogs.com/michael-shan/archive/2012/03/31/6649681.html

央视深入报道,国内主流芯片真实水平如何?

来源&#xff1a;芯师爷摘要&#xff1a; 站在风口上&#xff0c;猪都会飞&#xff01;——用这来概括当下国内芯片领域再恰当不过了。自中兴事件之后&#xff0c;很多创业者纷纷将商业计划的关键字调整为“芯片”。与此同时&#xff0c;投资者也将目光转移至AI芯片、自动驾驶芯…

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap

sqlmap 官网&#xff1a;http://sqlmap.org/ sqlmap文档地址&#xff1a;https://github.com/sqlmapproject/sqlmap/wiki/Usage sqlmap 使用 思维导图&#xff1a;http://download.csdn.net/detail/freeking101/9887831 黑帽与白帽都喜爱的十大SQL注入工具&#xff1a;http://…