又到了更新的时候,pyqt写软件还没有弄好,但是这周也不能算是完全没有进展的一周。下面就来复盘一下学到的pyqt基本知识
首先是所有知识系统的学习方法,按先后顺序可以看作是:控件的特性 控件的样式 资源的加载 控件的布局 事件的信号 动画特效 界面跳转 设计工具使用 额外(网络,多线程,数据库)
上面的结构基本上和我学习网页知识时候差不多,不过当时学习网页知识时候水平太低,撸的代码还是太少了,现在也都忘得差不多了。
复盘目标:信号槽机制 事件处理机制 定时器 vscode里面用户代码片段和自动补全设置
参数处理方式(self,*args,kwargvs)
关于事件处理机制我当然说不行,贴两个链接看完。
https://blog.****.net/qq_29344757/article/details/77994016
https://www.jianshu.com/p/48f007c2de09
信号槽机制:
信号槽机制(事件机制)是处理信号进行各类控件之间通信的核心机制
信号:当一个控件的状态发生改变时,向外界发出的信息。例如QPushButton1.pressed
信号可以是内置的也可以是自定义的
槽:一个执行某些操作的函数/方法,不同的控件里面有内置的槽函数,也可以自定义槽函数
信号与槽的链接通过object信号.connect(槽函数)来连接,一个信号可以连接多个槽函数,一个槽函数也可以监听多个信号。
一个简单的例子:
# -*-coding:utf-8 -*-
import io
import sys
# 改变标准输出的默认编码
sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='utf8')
from PyQt5.Qt import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class App(QApplication):
def notify(self, recevier, evt):
if recevier.inherits("QPushButton") and evt.type() == QEvent.MouseButtonPress:
print(recevier, evt)
return super().notify(recevier, evt)
class Btn(QPushButton):
def event(self, evt):
if evt.type() == QEvent.MouseButtonPress:
print(evt)
return super().event(evt)
def mousePressEvent(self, *args, **kwargs):
print("鼠标被按下..")
if __name__ == '__main__':
# 创建一个Qapplication类实例
app= App(sys.argv)
# 创建一个窗口
w=QWidget()
w.resize(300,150)
w.move(300,300)
w.setWindowTitle("事件代码机制")
btn=Btn(w)
btn.setText("按钮")
def cao():
print("按钮被按下了")
btn.pressed.connect(cao)
w.show()
# 进入程序的主循环,并通过exit函数安全结束
sys.exit(app.exec_())
上面代码中首先建立了pushbutton和cao函数之间的联系来验证信号与槽机制,然后在通过重写QApplication类里的notify函数和Qbushbutton类里的event函数来进行事件处理机制的验证使用。
关键的学习点在于:
1.对于面向对象方法,处理函数和封装的办法,主要是通过继承和重写机制,这就需要对于控件内部的函数具有极高的了解。
2.对于python基础要求掌握,重写QApplication里面notify函数的参数有哪些,使用recevier.inherits()和evt.type()进行事件的筛选,还有如何使用super()来返回原来需要返回的参数, def mousePressEvent(self, *args, **kwargs) 里面,当函数的参数不确定时,可以使用*args 和**kwargs,*args 没有key值,**kwargs有key值。
最后结果如图:
定时器:
定时器是通过软件来进行定时,看起来有点像多线程但又有区别,关于两者的区别我找了一篇文章,这里的定时器和单片机里的定时器应该不是一个东西,单片机中的定时器是硬件控制,和晶振的频率息息相关,而这里不一样:
https://blog.****.net/wangweitingaabbcc/article/details/6723606
定时器的使用;
# -*-coding:utf-8 -*-
import io
import sys
# 改变标准输出的默认编码
sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='utf8')
from PyQt5.Qt import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class MyObject(QObject):
def timerEvent(self, evt):
print(evt, "1")
class MyLabel(QLabel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setText("10")
self.move(100, 100)
self.setStyleSheet("font-size: 22px;")
def setSec(self, sec):
self.setText(str(sec))
def startMyTimer(self, ms):
self.timer_id = self.startTimer(ms)
def timerEvent(self, *args, **kwargs):
print("xx")
# 1. 获取当前的标签的内容
current_sec = int(self.text())
current_sec -= 1
self.setText(str(current_sec))
if current_sec == 0:
print("停止")
self.killTimer(self.timer_id)
# class MyWidget(QWidget):
# def timerEvent(self, *args, **kwargs):
# current_w = self.width()
# current_h = self.height()
# self.resize(current_w + 10, current_h + 10)
# 实现窗口大小控制功能
if __name__ == '__main__':
# 创建一个Qapplication类实例
app=QApplication(sys.argv)
# 创建一个窗口
w=QWidget()
w.resize(300,150)
w.move(300,300)
w.setWindowTitle("定时器使用")
label=MyLabel(w)
label.startTimer(1000)
w.startTimer(1000)
w.show()
# 进入程序的主循环,并通过exit函数安全结束
sys.exit(app.exec_())
定时器和多线程比起来还是比较简单,毕竟没有太多花里胡哨的东西,使用得多的就两个函数,一个startTimer一个killTimer。上面代码的难点在于面向对象的封装,例如重写QLabel时候要进行初始化,因为要用到别的paint事件来画图,中间还简单的使用了一下qss,在设置函数时候留下可操作性很高,比如设置时间。上面代码实现了简单的一个从10到1的倒计时功能。
vscode相关:
使用vscode写代码还是不是特别好,对于智能补全功能要求高的时候尤其显现出来,首先是pyqt自动补全的设置需要在setting.json里面添加路径,关键在于对于某些事件的补全不完全,和相关函数里面的参数不显示,例如上面事件处理机制中的notify()参数就很难知道有什么。这导致我在调代码时候因为mousePressEvent写成MousePressEvent导致结果和预期不一样。然后就是用户*代码的设置了,这个到没什么,在首选项中添加就是了,只不过写的时候稍微麻烦一点。总结就是可能还是需要下载一个pycharm了。