1. Tkinter
在Python3.x 中,默认安装Tkinter 库,在使用时引入即可(引入方式:import tkinter )
Tkinter 最大的好处,就是 python3 自带,真正的"绿色代码",不需另外安装第三方工具和框架(比如 wxPython/PyQt),后续工作少,坑也少,打包的程序也足够小!
GitHub上找到的 Tkinter 可视化编程工具:tkinter-designer
1.1 Tkinter GUI 编程介绍
创建一个 GUI 应用就像画画一样。传统上,艺术家使用单一的画布开展创作。其工作方式如下:首先会从一块干净的画布开始,该“画布”即用来构建其余组件的顶层窗口对象 ,而后才在“画布”上进行绘画。
窗口和控件
在 GUI 编程中,顶层的根窗口对象包含组成 GUI 应用的所有小窗口对象。它们可能是文字标签、按钮、列表框等。这些独立的 GUI 组件称为控件 。所以当我们说创建一个顶层窗口时,只是表示需要一个地方来摆放所有的控件。
控件可以独立存在,也可以作为容器存在。如果一个控件包含其他控件,就可以将其认为是那些控件的父控件 。相应地,如果一个控件被其他控件包含,则将其认为是那个控件的子控件 ,而父控件就是下一个直接包围它的容器控件。通常,控件有一些相关的行为,比如按下按钮、将文本写入文本框等。这些用户行为称为事件 ,而 GUI 对这类事件的响应称为回调 。
事件驱动处理 一个 GUI 应用从开始到结束就是通过整套事件体系(如鼠标键盘的点积等)来驱动的。这种方式称为事件驱动处理。
最简单的鼠标移动就是一个带有回调的事件的例子。假设鼠标指针正停在 GUI 应用顶层窗口的某处。如果你将鼠标移动到应用的另一部分,鼠标移动的行为会被复制到屏幕的光标上,于是看起来像是根据你的手移动的。
GUI 应用必须先创建所有的 GUI 组件,然后将它们绘制在屏幕上。这是 布局管理器(geometry manager) 的职责所在。当布局管理器排列好所有控件(包括顶层窗口)后,GUI 应用进入其类似服务器的无限循环。这个循环会一直运行,直到出现 GUI 事件,进行处理,然后再等待更多的事件去处理。
布局管理器
Tk 有 3 种布局管理器来帮助控件集进行定位。
- 最原始的一种称为 Placer;
- 第二种布局管理器会是你主要使用的,它叫做 Packer,它会把控件填充到正确的位置(即指定的父控件中),然后对于之后的每个控件,会去寻找剩余的空间进行填充。这个处理很像是旅行时往行李箱中填充行李的过程;
- 第三种布局管理器是 Grid。你可以基于网格坐标,使用 Grid 来指定GUI 控件的放置。Grid 会在它们的网格位置上渲染 GUI 应用中的每个对象。
1.2 控件
Tk 控件
之前提到过所有主要控件都是构建在顶层窗口对象之上的。该对象在 Tkinter 中使用 Tk类进行创建,然后进行如下实例化:
import Tkinter
top = Tkinter.Tk()
在这个窗口中,可以放置独立的控件,也可以将多个组件拼凑在一起来构成 GUI 程序。
以下是常用的 18 种 Tk 控件
控 件 | 描 述 |
---|
Button | 与 Label 类似,但提供额外的功能,如鼠标悬浮、按下、释放以及键盘活动/事件 | Canvas | 提供绘制形状的功能(线段、椭圆、多边形、矩形),可以包含图像或位图 | Checkbutton | 一组选框,可以勾选其中的任意个(与 HTML 的 checkbox 输入类似) | Entry | 单行文本框,用于收集键盘输入(与 HTML 的文本输入类似) | Frame | 包含其他控件的纯容器 | Label | 用于包含文本或图像 | LabelFrame | 标签和框架的组合,拥有额外的标签属性 | Listbox | 给用户显示一个选项列表来进行选择 | Menu | 按下 Menubutton 后弹出的选项列表,用户可以从中选择 | Menubutton | 用于包含菜单(下拉、级联等) | Message | 消息。与 Label 类似,不过可以显示成多行 | PanedWindow | 一个可以控制其他控件在其中摆放的容器控件 | Radiobutton | 一组按钮,其中只有一个可以“按下”(与 HTML 的 radio 输入类似) | Scale | 线性“滑块”控件,根据已设定的起始值和终止值,给出当前设定的精确值 | Scrollbar | 为 Text、Canvas、Listbox、Enter 等支持的控件提供滚动功能 | Spinbox | Entry 和 Button 的组合,允许对值进行调整 | Text | 多行文本框,用于收集(或显示)用户输入的文本(与 HTML 的 textarea 类似) | Toplevel | 与 Frame 类似,不过它提供了一个单独的窗口容器 |
Label 控件
以下是一个 Label 控件演示
import tkinter
top = tkinter.Tk()
label = tkinter.Label(top, text='hello world')
label.pack()
tkinter.mainloop()
运行结果是生成一个写有“hello world”的窗口;
Button 控件
import tkinter
top=tkinter.Tk()
quit=tkinter.Button(top,text='Quit',command=top.quit)
quit.pack()
tkinter.mainloop()
运行结果是生成一个写带有“Quit”选项的按钮窗口,按下并释放后,窗口进程关闭;
在 Packer 没有收到其他指示时,所有控件都是垂直排列的(自上而下依次排列)。如果想要水平布局则需要创建一个新的 Frame 对象来添加按钮。该框架将作为单个子对象来代替父对象的位置。
import tkinter
top=tkinter.Tk()
label=tkinter.Label(top,text='hello world')
label.pack()
quit=tkinter.Button(top,text='quit',command=top.quit)
quit.pack(fill=tkinter.X,expand=1)
tkinter.mainloop()
Scale 控件
Scale 用于与 Label 控件进行交互。Scale 滑块是用来控制 Label 控件中文字字体大小的工具。滑块的位置值越大,字体越大;反之亦然。
from tkinter import *
def resize(ev=None):
label.config(font='Helvetica -%d bold'%scale.get())
top=Tk()
top.geometry('250x150')
label=Label(top,text='hello world',font='Helvetica -12 bold')
label.pack(fill=X, expand=1)
scale=Scale(top,from_=10,to=40,orient=HORIZONTAL,command=resize)
scale.set(12)
scale.pack(fill=X,expand=1)
quit=Button(top,text='quit',command=top.quit,activeforeground='white',activebackground='red')
quit.pack()
mainloop()
1.3 偏函数应用示例
偏函数在 Python 2.5 版本中添加进来,是函数式编程一系列重要改进中的一部分。使用偏函数,可以通过有效地“冻结”那些预先确定的参数来缓存函数参数,然后在运行时,当获得需要的剩余参数后,可以将它们解冻,传递到最终的参数中,从而使用最终确定的所有参数去调用函数。
偏函数最好的一点是它不只局限于函数。偏函数可以用于可调用对象(任何包括函数接口的对象),只需要通过使用圆括号即可,包括类、方法或可调用实例。对于有很多可调用对象,并且许多调用都反复使用相同参数的情况,使用偏函数会非常合适。
GUI 编程是一个很好的偏函数用例,因为你很有可能需要 GUI 控件在外观上具有某种一致性,而这种一致性来自于使用相同参数创建相似的对象时。我们现在要实现一个应用,在这个应用中有很多按钮拥有相同的前景色和背景色。对于这种只有细微差别的按钮,每次都使用相同的参数创建相同的实例简直是一种浪费:前景色和背景色都是相同的,只有文本有一点不同。
在下面的示例中你可以看到它是如何一步步展开并最终调用到最底层的;
from functools import partial as pto
from tkinter import Tk,Button,X
from tkinter.messagebox import showerror,showinfo,showwarning
WARN='warn'
CRIT='crit'
REGU='regu'
SIGNS={
'do not enter':CRIT,
'railroad crossing':WARN,
'55 speed limit':REGU,
'wrong way':CRIT,
'merging traffic':WARN,
'obe way':REGU,
}
critCB=lambda:showerror('Error','Error Button Pressed')
warnCB=lambda:showwarning('Warning', 'Warning Button Pressed!')
infoCB=lambda:showinfo('Info','Info Button Pressed')
top=Tk()
top.geometry('250x250')
top.title('Rod Signs')
MyButton=pto(Button,top)
CritButton=pto(MyButton,command=critCB,bg='white',fg='red')
WarnButton=pto(MyButton,command=warnCB,bg='goldenrod1')
ReguButton=pto(MyButton,command=infoCB,bg='white')
for sign in SIGNS:
signType=SIGNS[sign]
cmd='%sButton(text=%r%s).pack(fill=X,expand=True)'%(signType.title(),sign,'.upper()'if signType==CRIT else '.title()')
eval(cmd)
Button(top,text='Quit',command=top.quit,bg='red',fg='yellow').pack(fill=X,expand=1)
top.mainloop()
1.4 文件系统遍历 GUI 示例
import os
from time import sleep
from tkinter import *
from tkinter import TclError
class DirList(object):
def __init__(self,initdir=None):
self.top=Tk()
self.label=Label(self.top,text='directory lister v1.1')
self.label.pack()
self.cwd=StringVar(self.top)
self.dirl=Label(self.top,fg='blue',font=('Helvetica',12,'bold'))
self.dirl.pack()
self.dirfm=Frame(self.top)
self.dirsb=Scrollbar(self.dirfm)
self.dirsb.pack(side=RIGHT,fill=Y)
self.dirs=Listbox(self.dirfm,height=15,width=50,yscrollcommand=self.dirsb.set)
self.dirs.bind('<Double-1>',self.setDirAndGo)
self.dirsb.config(command=self.dirs.yview)
self.dirs.pack()
self.dirfm.pack()
self.dirn=Entry(self.top,width=50,textvariable=self.cwd)
self.dirn.bind('<Return>',self.dols)
self.dirn.pack()
self.bfm=Frame(self.top)
self.clr=Button(self.bfm,text='clear',command=self.clrDir,activeforeground='white',activebackground='blue')
self.ls=Button(self.bfm,text='list directory',command=self.dols,activeforeground='white',activebackground='green')
self.quit=Button(self.bfm,text='Quit',command=self.top.quit,activeforeground='white',activebackground='red')
self.clr.pack()
self.ls.pack()
self.quit.pack()
self.bfm.pack()
if initdir:
self.cwd.set(os.curdir)
self.dols()
def clrDir(self,ev=None):
self.cwd.set('')
def setDir(self,ev=None):
check=self.dirs.get(self.dirs.curselection())
self.cwd.set(check)
print(check)
self.dirn.update()
def setDirAndGo(self,ev=None):
self.last=self.cwd.get()
self.dirs.config(selectbackground='red')
check=self.dirs.get(self.dirs.curselection())
if not check:
check=os.curdir
self.cwd.set(check)
self.dols()
def dols(self,ev=None):
error=''
tdir=self.cwd.get()
if tdir=='.':
try:
tdir=self.dirs.get(self.dirs.curselection())
except:
pass
if not tdir:
tdir=os.curdir
if not os.path.exists(tdir):
error=tdir+':'+'no such file'
elif not os.path.isdir(tdir):
error=tdir+':'+'not a directory'
if error:
self.cwd.set(error)
self.top.update()
sleep(1)
if not (hasattr(self,'last') and self.last):
self.last=os.curdir
self.cwd.set(self.last)
self.dirs.config(selectbackground='LightSkyBlue')
self.top.update()
return
self.cwd.set('FETCHING DIRECTORY CONTENTS...')
self.top.update()
dirlist=os.listdir(tdir)
dirlist.sort()
os.chdir(tdir)
self.dirl.config(text=os.getcwd())
self.dirs.delete(0,END)
self.dirs.insert(END,os.curdir)
self.dirs.insert(END,os.pardir)
for eachFile in dirlist:
self.dirs.insert(END,eachFile)
self.cwd.set(os.curdir)
self.dirs.config(selectbackground='LightSkyBlue')
def main():
d=DirList(os.curdir)
mainloop()
if __name__=='__main__':
main()
1.5 其他 GUI 示例
这将使用 4 个流行的工具包实现同一个简单的 GUI 应用,这 4 个工具包分别是:Tix(Tk 接口扩展)、Pmw(Python MegaWidgets Tkinter扩展)、wxPython(wxWidgets 的 Python 版本)以及 PyGTK(GTK+的 Python 版本)
from tkinter import Label,Button,END
from tkinter.tix import Tk,Control,ComboBox
top=Tk()
label=Label(top,text='Anmials(in pairs;min:pair,max:dozen)')
label.pack()
ct=Control(top,label='Number:',integer=True,max=12,min=2,value=2,step=2)
ct.label.config(font='Helvetival -14 bold')
ct.pack()
cb=ComboBox(top,label='Type:',editable=True)
cb.label.config(font='Helvetival -14')
for anmail in ('dog','cat','hamster','python'):
cb.insert(END,anmail)
cb.pack()
qb=Button(top,text='Quit',command=top.quit,bg='red',fg='white')
qb.pack()
top.mainloop()
from tkinter import Label,Button,END,W
from Pmw import initialise,ComboBox,Counter
top=initialise()
label=Label(top,text='Anmials(in pairs;min:pair,max:dozen)')
label.pack()
ct=Counter(top,labelpos=W,label_text='Number:',datatype='integer',
entryfield_value=2,increment=2,
entryfield_validate={'validator':'integer','max':12,'min':2})
ct.pack()
cb=ComboBox(top,labelpos=W,label_text='Type')
for anmail in ('dog','cat','hamster','python'):
cb.insert(END,anmail)
cb.pack()
qb=Button(top,text='Quit',command=top.quit,bg='red',fg='white')
qb.pack()
top.mainloop()
2. PyQt5
官方教程
2.1 环境搭载
2.1.1 安装pyQT5模块包
方法一:到Pycharm工程解析器(project interpreter)中搜索PyQt5 并添加到工程中; 方法二:管理员下运行cmd - 输入pip install pyQt5 ; 方法三:到PyQt5下载页面下载对应whl 文件,管理员下运行cmd - cd + whl所在目录 - pip install + whl全名 ;
2.1.2 安装PyQt5-tools模块包
方法一:管理员下运行cmd - 输入pip install pyQt5-tools ; 方法二:到pyqt5-tools下载页面下载对应python版本和电脑版本的whl 文件,管理员下运行cmd - cd + whl所在目录 - pip install + whl全名 ;
如:python3.7 和 64位系统选择:pyqt5_tools-5.13.0.1.5-cp37-none-win_amd64.whl
2.1.3 配置QtDesigner和pyUIC
QtDesigner 可实现可视化构造UI界面,一般安装PyQt5后,系统会默认安装QtDesigner工具;
1. 配置QT设计界面“Qt Designer”
Pycharm --> File --> setting --> Tools --> External Tools --> 左上角 + 号Add ,填入对应参数:
- Name:工具名,自定义,可填 QtDesigner
- Program:运行程序,选择
designer.exe
参考路径:C:\Users\你的用户名\AppData\Local\Programs\Python\Python37\Lib\site-packages\pyqt5_tools\Qt\bin\designer.exe
- Working directory:工作路径,默认即可
参考路径:C:\Users\你的用户名\AppData\Local\Programs\Python\Python37\Lib\site-packages\pyqt5_tools\Qt\bin
2. 配置.ui转.py工具“pyUIC”
同上操作,新添加一个Tools,填入对应参数: Name:工具名,自定义,可填 PyUIC
参考路径:C:\Users\你的用户名\AppData\Local\Programs\Python\Python37\Scripts\pyuic5.exe
- Arguments:参数,填入:
$FileName$ -o $FileNameWithoutExtension$.py - Working directory:工作路径,
$ProjectFileDir$
完成上述两项操作后,记得Apply 和 OK !!!
2.2 使用说明
2.2.1 新建窗体
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("sb")
window.resize(500, 500)
window.move(0, 0)
label = QLabel(window)
label.setText("sb")
label.move(200, 200)
window.show()
sys.exit(app.exec_())
2.2.2 类继承
from PyQt5.Qt import *
class Window(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Window-Title")
self.resize(500, 500)
self.setup_ui()
def QObject继承结构测试(self):
mros = QObject.mro()
for mro in mros:
print(mro)
def setup_ui(self):
self.QObject继承结构测试()
self.QObject类型判定()
self.QObject对象的父子关系操作()
self.QObject信号的操作()
self.QObject对象名称和属性的操作()
self.QObject对象释放()
def QObject类型判定(self):
label1 = QLabel(self)
label1.setText("sb")
label1.move(100, 100)
label2 = QLabel(self)
label2.setText("sbbbbb")
label2.move(0, 150)
label2.deleteLater()
btn = QPushButton(self)
btn.setText("一个按钮")
btn.move(200, 200)
for widget in self.children():
print(widget)
if widget.isWidgetType():
widget.setStyleSheet("background-color: cyan;")
def QObject对象的父子关系操作(self):
obj1 = QObject()
self.obj1 = obj1
obj2 = QObject()
obj2.setParent(obj1)
obj2.destroyed.connect(lambda: print("obj2对象被释放了"))
del self.obj1
def QObject信号的操作(self):
def destroy_cao(obj):
print("对象被释放了", obj)
def obj_name_cao(name):
print("对象名称发生了改变", name)
self.obj = QObject()
self.obj.destroyed.connect(destroy_cao)
self.obj.objectNameChanged.connect(obj_name_cao)
self.obj.objectNameChanged.disconnect(obj_name_cao)
self.obj.setObjectName("改变对象名字")
print(self.obj.receivers(self.obj.objectNameChanged))
print(self.obj.signalsBlocked(), "还没被阻断")
self.obj.blockSignals(True)
print(self.obj.signalsBlocked(), "信号被阻断")
self.obj.blockSignals(False)
print(self.obj.signalsBlocked(), "信号恢复了")
def cao():
print("按钮被点击")
btn = QPushButton(self)
btn.setText("点击我")
btn.clicked.connect(cao)
def QObject继承结构测试(self):
mros = QObject.mro()
for mro in mros:
print(mro)
def QObject对象名称和属性的操作(self):
with open("QObject.qss", "r") as f:
qApp.setStyleSheet(f.read())
label = QLabel(self)
label.setObjectName("notice")
label.setProperty("notice_level", "warning")
label.setText("warning")
label.setStyleSheet("font-size: 20px; color: red;")
label2 = QLabel(self)
label2.move(100, 100)
label2.setObjectName("notice")
label2.setProperty("notice_level", "error")
label2.setText("error")
print(label.dynamicPropertyNames())
print(label2.parentWidget())
def QObject对象释放(self):
obj1 = QObject()
self.obj1 = obj1
obj2 = QObject()
obj3 = QObject()
obj3.setParent(obj2)
obj2.setParent(obj1)
obj1.destroyed.connect(lambda: print("obj1被释放了"))
obj2.destroyed.connect(lambda: print("obj2被释放了"))
obj3.destroyed.connect(lambda: print("obj3被释放了"))
obj2.deleteLater()
print(obj1.children())
print(obj2)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = Window()
window.show()
print(window.childAt(255, 255))
print(window.childrenRect())
sys.exit(app.exec_())
参考: QObject Python super() 函数 Qt deletelater函数分析 Setparent函数用法技巧
2.2.3 定时器事件
from PyQt5.Qt import *
import sys
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("计时一次")
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)
app = QApplication(sys.argv)
window = MyWidget()
window.setWindowTitle("QObject定时器的使用")
window.resize(500, 500)
window.startTimer(1000)
label = MyLabel(window)
label.setSec(5)
label.startMyTimer(1000)
window.show()
sys.exit(app.exec_())
2.2.4 键盘鼠标事件
from PyQt5.Qt import *
import sys
class MyLabel(QLabel):
def enterEvent(self, *args, **kwargs):
print("鼠标进入")
self.setText("鼠标进入")
def leaveEvent(self, *args, **kwargs):
print("鼠标离开")
self.setText("鼠标离开")
def keyPressEvent(self, evt):
print("检测到键盘被按下")
if evt.key() == Qt.Key_Tab:
print("----- 被点击的是 Tab 键")
if evt.modifiers() == Qt.ControlModifier and evt.key() == Qt.Key_S:
print("----- 组合键被按下,ctrl + S 被点击")
if evt.modifiers() == Qt.ControlModifier | Qt.ShiftModifier and evt.key() == Qt.Key_A:
print("----- 组合键被按下,ctrl + Shift + A 被点击")
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("鼠标操作案例")
window.resize(500, 500)
label = MyLabel(window)
label.resize(200, 200)
label.move(100, 100)
label.setStyleSheet("background-color: cyan;")
label.grabKeyboard()
window.show()
sys.exit(app.exec_())
2.2.5 层级关系调整
from PyQt5.Qt import *
import sys
class Label(QLabel):
def mousePressEvent(self, evt):
self.raise_()
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("层级关系调整")
window.resize(500, 500)
label1 = Label(window)
label1.setText("标签1")
label1.resize(200, 200)
label1.setStyleSheet("background-color: red;")
label2 = Label(window)
label2.setText("标签2")
label2.resize(200, 200)
label2.setStyleSheet("background-color: green;")
label2.move(100, 100)
window.show()
sys.exit(app.exec_())
2.2.6 窗体状态
from PyQt5.Qt import *
import sys
class Window(QWidget):
def mousePressEvent(self, QMouseEvent):
if self.isMaximized():
self.showNormal()
else:
self.showMaximized()
app = QApplication(sys.argv)
window = Window()
window.resize(500, 500)
window.setWindowTitle("w1")
icon = QIcon("xxx.png")
window.setWindowIcon(icon)
print(window.windowIcon())
window.setWindowOpacity(0.9)
print(window.windowOpacity())
print(window.windowState() == Qt.WindowNoState)
window.show()
sys.exit(app.exec_())
Qt::WindowStates 类型有以下几个取值:
-
Qt::WindowNoState:无标志,正常状态,默认状态。 -
Qt::WindowMinimized:最小化状态。 -
Qt::WindowMaxmized:最大化状态。 -
Qt::WindowFullScreen:全屏状态。 -
Qt::WindowActive:激活状态。
参考: Qt 常用类 (9)—— QWidget
2.2.7 窗体大小
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
window = QWidget()
window.move(200, 100)
window.setFixedSize(500, 500)
print(window.x())
print(window.width())
print(window.geometry())
label = QLabel(window)
label.setText("sb")
label.move(100, 100)
label.setStyleSheet("background-color: cyan;")
def changeCao():
new_content = label.text() + "+1 "
label.setText(new_content)
label.adjustSize()
btn = QPushButton(window)
btn.setText("增加内容")
btn.move(100, 300)
btn.clicked.connect(changeCao)
window.show()
sys.exit(app.exec_())
2.2.8 【案例】无边框窗体
from PyQt5.Qt import *
import sys
class Window(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setWindowFlags(Qt.FramelessWindowHint)
self.setWindowOpacity(0.9)
self.setWindowTitle("顶层窗口操作-案例")
self.resize(500, 500)
self.top_margin = 10
self.btn_w = 80
self.btn_h = 40
self.setup_ui()
def setup_ui(self):
close_btn = QPushButton(self)
self.close_btn = close_btn
close_btn.setText("关闭")
close_btn.resize(self.btn_w, self.btn_h)
max_btn = QPushButton(self)
self.max_btn = max_btn
max_btn.setText("最大化")
max_btn.resize(self.btn_w, self.btn_h)
mini_btn = QPushButton(self)
self.mini_btn = mini_btn
mini_btn.setText("最小化")
mini_btn.resize(self.btn_w, self.btn_h)
def max_normal():
if self.isMaximized():
self.showNormal()
max_btn.setText("最大化")
else:
self.showMaximized()
max_btn.setText("恢复")
close_btn.pressed.connect(self.close)
max_btn.pressed.connect(max_normal)
mini_btn.pressed.connect(self.showMinimized)
def resizeEvent(self, QResizeEvent):
print("窗口大小发生了改变")
window_w = self.width()
close_btn_x = window_w - self.btn_w
close_btn_y = self.top_margin
self.close_btn.move(close_btn_x, close_btn_y)
max_btn_x = close_btn_x - self.btn_w
max_btn_y = self.top_margin
self.max_btn.move(max_btn_x, max_btn_y)
mini_btn_x = max_btn_x - self.btn_w
mini_btn_y = self.top_margin
self.mini_btn.move(mini_btn_x, mini_btn_y)
def mousePressEvent(self, QMouseEvent):
pass
def mouseMoveEvent(self, QMouseEvent):
pass
def mouseReleaseEvent(self, QMouseEvent):
pass
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
参考 setWindowFlags设置窗口属性
2.2.9 【案例】窗体综合
from PyQt5.Qt import *
import sys
class Window(QWidget):
def mousePressEvent(self, evt):
local_x = evt.x()
local_y = evt.y()
sub_widget = self.childAt(local_x, local_y)
if sub_widget is not None:
sub_widget.setStyleSheet("background-color: red;")
print(local_x, local_y, "被点击了")
app = QApplication(sys.argv)
window = Window()
window.setWindowTitle("父子关系案例")
window.resize(500, 500)
for i in range(1, 11):
label = QLabel(window)
label.setText("标签" + str(i))
label.move(40*i, 40*i)
window.show()
sys.exit(app.exec_())
2.2.10 控件交互
from PyQt5.Qt import *
import sys
class Window(QWidget):
def paintEvent(self, evt):
print("窗口被绘制了")
return super().paintEvent(evt)
class Btn(QPushButton):
def paintEvent(self, evt):
print("按钮被绘制了")
return super().paintEvent(evt)
app = QApplication(sys.argv)
window = Window()
window.setWindowTitle("交互状态")
window.resize(500, 500)
btn = Btn(window)
btn.setText("按钮")
btn.destroyed.connect(lambda : print("按钮被释放了"))
window.show()
sys.exit(app.exec_())
参考: Qt 窗口属性简介之Qt::WA_DeleteOnClose
2.2.11 【案例】简单登录界面
from PyQt5.Qt import *
class Window(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("简单登录界面")
self.resize(500, 500)
self.setup_ui()
def setup_ui(self):
label = QLabel(self)
label.setText("请输入登录密码:")
label.move(100, 50)
le = QLineEdit(self)
le.move(100, 100)
btn = QPushButton(self)
btn.setText("登录")
btn.move(100, 150)
btn.setEnabled(False)
def text_cao(text):
print("文本内容发生了改变", text)
btn.setEnabled(len(text) > 0)
if len(text) == 0:
label.setText("请输入登录密码:")
if text == "2333":
label.setText("登录成功")
else:
pass
label.show()
label.adjustSize()
def check():
print("按钮被点击了")
content = le.text()
if content != "2333":
label.setText("登录失败")
else:
pass
label.show()
label.adjustSize()
le.textChanged.connect(text_cao)
btn.pressed.connect(check)
btn.pressed.connect(check)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
2.2.12 焦点控制
from PyQt5.Qt import *
import sys
class Window(QWidget):
def mousePressEvent(self, evt):
print(self.focusWidget())
self.focusNextPrevChild(True)
app = QApplication(sys.argv)
window = Window()
window.setWindowTitle("焦点控制")
window.resize(500, 500)
le1 = QLineEdit(window)
le1.move(50, 50)
le2 = QLineEdit(window)
le2.move(100, 100)
le3 = QLineEdit(window)
le3.move(150, 150)
QWidget.setTabOrder(le1, le2)
QWidget.setTabOrder(le2, le3)
le1.setFocus()
window.show()
print(le1)
print(le2)
print(le3)
sys.exit(app.exec_())
2.2.13 事件响应函数
from PyQt5.Qt import *
class Window(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("事件消息的学习")
self.resize(500, 500)
self.setup_ui()
def setup_ui(self):
pass
def showEvent(self, QShowEvent):
print("窗口被展示了出来")
def closeEvent(self, QCloseEvent):
print("窗口被关闭了")
def moveEvent(self, QMoveEvent):
print("窗口被移动了")
def resizeEvent(self, QResizeEvent):
print("窗口改变了尺寸大小")
def enterEvent(self, QEvent):
print("鼠标进来了")
self.setStyleSheet("background-color: yellow;")
def leaveEvent(self, QEvent):
print("鼠标移开了")
self.setStyleSheet("background-color: green;")
def mousePressEvent(self, QMouseEvent):
print("鼠标被按下")
def mouseReleaseEvent(self, QMouseEvent):
print("鼠标被释放")
def mouseDoubleClickEvent(self, QMouseEvent):
print("鼠标双击")
def mouseMoveEvent(self, QMouseEvent):
print("鼠标移动了")
def keyPressEvent(self, QKeyEvent):
print("键盘上某一个按键被按下了")
def keyReleaseEvent(self, QKeyEvent):
print("键盘上某一个按键被释放了")
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
在这里插入代码片
参考: 从Qt到PyQt - event()事件处理机制 QMainWindow PyQt5 实现状态栏(statusBar)显示和隐藏功能
2.2.14 控件信息提示 [状态栏、help 按钮]
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
window = QMainWindow()
window.setWindowTitle("信息提示案例")
window.resize(500, 500)
window.setWindowFlags(Qt.WindowContextHelpButtonHint)
window.statusBar()
window.setStatusTip("您已进入本窗口")
print(window.statusTip())
label = QLabel(window)
label.setText("sb")
label.setStatusTip("这是标签")
label.setToolTip("这是一个提示标签")
print(label.toolTip())
print(label.toolTipDuration())
label.setWhatsThis("这是标签1111")
window.show()
sys.exit(app.exec_())
2.2.15 窗体尺寸控制
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("最小尺寸最大尺寸限定")
window.setMinimumSize(200, 200)
window.setMaximumSize(500, 500)
window.show()
sys.exit(app.exec_())
2.2.16 各种按钮功能测试
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("按钮的功能测试-抽象类")
window.resize(500, 500)
btn = QPushButton(window)
btn.move(300, 200)
def plus_one():
print("加一")
num = int(btn.text()) + 1
btn.setText(str(num))
btn.setText("1")
btn.pressed.connect(plus_one)
icon = QIcon("xxx.png")
btn.setIcon(icon)
size = QSize(20, 20)
btn.setIconSize(size)
print(btn.icon())
print(btn.iconSize())
btn.setShortcut("Alt+c")
btn.setAutoRepeat(True)
btn.setAutoRepeatDelay(200)
btn.setAutoRepeatInterval(100)
print(btn.autoRepeat())
print(btn.autoRepeatInterval())
print(btn.autoRepeatDelay())
push_button = QPushButton(window)
push_button.setText("这是QPushButton")
push_button.move(300, 100)
radio_button = QRadioButton(window)
radio_button.setText("这是一个radio")
radio_button.move(100, 150)
checkbox = QCheckBox(window)
checkbox.setText("这是checkbox")
checkbox.move(100, 200)
push_button.setStyleSheet("QPushButton:pressed {background-color: red;}")
push_button.setDown(True)
radio_button.setDown(True)
checkbox.setDown(True)
push_button.setCheckable(True)
print(push_button.isCheckable())
print(radio_button.isCheckable())
print(checkbox.isCheckable())
radio_button.setChecked(True)
push_button.setChecked(True)
checkbox.setChecked(True)
print(push_button.isChecked())
print(radio_button.isChecked())
print(checkbox.isChecked())
def cao():
push_button.toggle()
radio_button.toggle()
checkbox.toggle()
push_button.setChecked(not push_button.isChecked())
btn.pressed.connect(cao)
push_button.setEnabled(True)
radio_button.setEnabled(True)
checkbox.setEnabled(True)
for i in range(0, 3):
btn5 = QCheckBox(window)
btn5.setText("btn" + str(i))
btn5.move(50 * i, 50 * i)
btn5.setAutoExclusive(True)
print(btn5.autoExclusive())
print(btn5.isCheckable())
btn5.setCheckable(True)
btn9 = QPushButton(window)
btn9.setText("这是按钮")
btn9.move(200, 200)
btn9.pressed.connect(lambda :print("点击了这个按钮"))
btn9.click()
btn9.animateClick(2000)
class Btn(QPushButton):
def hitButton(self, point):
import math
print(point)
if point.x() > self.width() / 2:
return True
return False
yuanxin_x = self.width() / 2
yuanxin_y = self.height() / 2
hit_x = point.x()
hit_y = point.y()
distance = math.sqrt(math.pow(hit_x - yuanxin_x, 2) + math.pow(hit_y - yuanxin_y, 2))
if distance < self.width() / 2:
return True
return False
def paintEvent(self, evt):
super().paintEvent(evt)
painter = QPainter(self)
painter.setPen(QPen(QColor(100, 150, 200), 6))
painter.drawEllipse(self.rect())
btn0 = Btn(window)
btn0.move(200, 300)
btn0.setText("点击")
btn0.resize(200, 200)
btn.setCheckable(True)
btn.pressed.connect(lambda : print("按钮被按下了"))
btn.released.connect(lambda : print("按钮鼠标被释放了"))
btn.clicked.connect(lambda value: print("按钮被点击", value))
btn0.toggled.connect(lambda value: print("按钮选中状态发生了改变", value))
window.show()
sys.exit(app.exec_())
参考: Qt5 Python GUI 编程指南
2.2.17 绘制事件
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("QAbstractButton")
window.resize(300, 200)
class Btn(QAbstractButton):
def paintEvent(self, evt):
painter = QPainter(self)
pen = QPen(QColor(111, 200, 20), 2)
painter.setPen(pen)
painter.drawText(25, 40, self.text())
painter.drawEllipse(0, 0, 50, 100)
btn = Btn(window)
btn.setText("xxx")
btn.resize(200, 200)
btn.pressed.connect(lambda : print("点击了这个按钮"))
window.show()
sys.exit(app.exec_())
参考: QT-QPainter介绍
2.2.18 右击菜单和按钮下拉菜单
from PyQt5.Qt import *
import sys
class Window(QWidget):
def contextMenuEvent(self, evt):
print("默认上下文菜单调用这个方法")
menu = QMenu(self)
open_recent_menu = QMenu(menu)
open_recent_menu.setTitle("最近打开")
open_recent_menu.setIcon()
new_action = QAction()
new_action.setText("新建")
new_action.setIcon(QIcon("xxx.png"))
new_action = QAction(QIcon("xxx.png"), "新建", menu)
new_action.triggered.connect(lambda: print("新建文件"))
open_action = QAction(QIcon("xxx.png"), "打开", menu)
open_action.triggered.connect(lambda: print("打开文件"))
exit_action = QAction("退出", menu)
exit_action.triggered.connect(lambda: print("退出程序"))
file_action = QAction("Python-GUI编程-PyQt5")
menu.addAction(new_action)
menu.addAction(open_action)
open_recent_menu.addAction(file_action)
menu.addMenu(open_recent_menu)
menu.addSeparator()
menu.addAction(exit_action)
menu.exec_(evt.globalPos())
app = QApplication(sys.argv)
window = Window()
window.setWindowTitle("按钮的功能")
window.resize(500, 500)
btn = QPushButton(window)
btn.setParent(window)
btn.setText("xxx")
btn.setIcon(QIcon("xxx.png"))
menu = QMenu(window)
open_recent_menu = QMenu(menu)
open_recent_menu.setTitle("最近打开")
open_recent_menu.setIcon(QIcon("xxx.png"))
new_action = QAction(QIcon("xxx.png"), "新建", menu)
new_action.triggered.connect(lambda :print("新建文件"))
open_action = QAction(QIcon("xxx.png"), "打开", menu)
open_action.triggered.connect(lambda :print("打开文件"))
exit_action = QAction("退出", menu)
exit_action.triggered.connect(lambda :print("退出程序"))
file_action = QAction("Python-GUI编程-PyQt5")
menu.addAction(new_action)
menu.addAction(open_action)
open_recent_menu.addAction(file_action)
menu.addMenu(open_recent_menu)
menu.addSeparator()
menu.addAction(exit_action)
btn.setMenu(menu)
print(btn.menu())
btn.setStyleSheet("QPushButton border:none;")
btn.setFlat(True)
print(btn.isFlat())
btn2 = QPushButton(window)
btn2.setText("btn2")
btn2.move(200, 200)
btn2.setAutoDefault(True)
print(btn.autoDefault())
print(btn2.autoDefault())
def show_menu(point):
menu = QMenu(window)
open_recent_menu = QMenu(menu)
open_recent_menu.setTitle("最近打开")
new_action = QAction(QIcon("xxx.png"), "新建", menu)
new_action.triggered.connect(lambda: print("新建文件"))
open_action = QAction(QIcon("xxx.png"), "打开", menu)
open_action.triggered.connect(lambda: print("打开文件"))
exit_action = QAction("退出", menu)
exit_action.triggered.connect(lambda: print("退出程序"))
file_action = QAction("Python-GUI编程-PyQt5")
menu.addAction(new_action)
menu.addAction(open_action)
open_recent_menu.addAction(file_action)
menu.addMenu(open_recent_menu)
menu.addSeparator()
menu.addAction(exit_action)
dest_point = window.mapToGlobal(point)
menu.exec_(dest_point)
window.setContextMenuPolicy(Qt.CustomContextMenu)
window.customContextMenuRequested.connect(show_menu)
btn.show()
window.show()
btn.showMenu()
sys.exit(app.exec_())
参考: QPushButton 之 default、autoDefault 分析
2.2.19 工具按钮
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("QToolButton使用")
window.resize(500, 500)
tb = QToolButton(window)
tb.setText("工具按钮")
tb.setIcon(QIcon("xxx.png"))
tb.setIconSize(QSize(30, 30))
tb.setToolTip("这是一个新建按钮")
tb.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
tb.setAutoRaise(True)
menu = QMenu(tb)
menu.setTitle("菜单")
sub_menu = QMenu(menu)
sub_menu.setTitle("子菜单")
sub_menu.setIcon(QIcon("xxx.png"))
action1 = QAction(QIcon("xxx.png"), "行为1", menu)
action1.setData([1, 2, 3])
action2 = QAction("行为2", menu)
action2.setData({"name": "sz"})
action1.triggered.connect(lambda :print("点击了行为菜单选项"))
menu.addMenu(sub_menu)
menu.addSeparator()
menu.addAction(action1)
menu.addAction(action2)
tb.clicked.connect(lambda :print("工具按钮被点击了"))
tb.setMenu(menu)
tb.setPopupMode(QToolButton.MenuButtonPopup)
def do_action(action):
print("点击了行为", action.data())
tb.triggered.connect(do_action)
btn = QPushButton(window)
btn.setText("一般按钮")
btn.move(100, 100)
btn.setFlat(True)
btn.setMenu(menu)
tb.setArrowType(Qt.RightArrow)
window.show()
sys.exit(app.exec_())
参考: QToolButton
2.2.20 radio 选中按钮
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("QRadioButton-功能测试")
window.resize(500, 500)
red = QWidget(window)
red.resize(200, 200)
red.setStyleSheet("background-color: red;")
red.move(50, 50)
green = QWidget(window)
green.resize(200, 200)
green.setStyleSheet("background-color: green;")
green.move(red.x() + red.width(), red.y() + red.height())
rb_nan = QRadioButton("男-&Male", red)
rb_nan.move(10, 10)
rb_nan.setChecked(True)
rb_nv = QRadioButton("女-&Female", red)
rb_nv.move(10, 50)
rb_nv.setIcon(QIcon("xxx.png"))
rb_nv.setIconSize(QSize(20, 20))
rb_nv.toggled.connect(lambda isChecked: print(isChecked))
rb_nv.setAutoExclusive(True)
rb_yes = QRadioButton("yes", green)
rb_yes.move(10, 10)
rb_no = QRadioButton("no", green)
rb_no.move(10, 50)
window.show()
sys.exit(app.exec_())
2.2.21 按钮组设定与管理
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("按钮组的使用")
window.resize(500, 500)
r_male = QRadioButton("男", window)
r_female = QRadioButton("女", window)
r_male.move(100, 100)
r_female.move(100, 150)
r_male.setChecked(True)
sex_group = QButtonGroup(window)
sex_group.addButton(r_male, 1)
sex_group.addButton(r_female, 2)
r_yes = QRadioButton("是", window)
r_no = QRadioButton("否", window)
r_yes.move(300, 100)
r_no.move(300, 150)
answer_group = QButtonGroup(window)
answer_group.addButton(r_yes)
answer_group.addButton(r_no)
answer_group.setId(r_yes, 1)
answer_group.setId(r_no, 2)
print(answer_group.id(r_yes))
print(answer_group.id(r_no))
r_no.setChecked(True)
print(answer_group.checkedId())
sex_group.setExclusive(True)
print(sex_group.buttons())
print(sex_group.button(2))
print(sex_group.checkedButton())
def test(val):
print(sex_group.id(val))
sex_group.buttonClicked.connect(test)
window.show()
sys.exit(app.exec_())
2.2.22 选中框
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("QCheckBox 功能测试")
window.resize(500, 500)
cb = QCheckBox("&Python", window)
cb.setIcon(QIcon("xxx.png"))
cb.setIconSize(QSize(60, 60))
cb.setTristate(True)
cb.setChecked(True)
cb.setCheckState(Qt.PartiallyChecked)
cb.setCheckState(Qt.Checked)
cb.toggled.connect(lambda isChecked: print(isChecked))
window.show()
sys.exit(app.exec_())
参考; Qt之QCheckBox
2.2.23 输入框
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("QLineEdit功能测试")
window.resize(500, 500)
le_a = QLineEdit(window)
le_a.move(100, 200)
le_b = QLineEdit(window)
le_b.move(100, 300)
le_b.setEchoMode(QLineEdit.PasswordEchoOnEdit)
print(le_b.echoMode())
copy_btn = QPushButton(window)
copy_btn.setText("复制")
copy_btn.move(100, 400)
def copy_cao():
content = le_a.text()
le_b.setText(content)
le_b.setText("")
le_b.insert(content)
print(le_b.text())
print(le_b.displayText())
print(le_b.isModified())
le_b.setModified(False)
copy_btn.clicked.connect(copy_cao)
le_a.setMaxLength(3)
print(le_a.maxLength())
le_a.setReadOnly(False)
le_a.setText("2333")
window.show()
sys.exit(app.exec_())
参考: setEchoMode()设置模式
2.2.24 输入框内容编辑
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("QLineEdit-功能测试")
window.resize(500, 500)
le = QLineEdit(window)
le.move(100, 100)
le.resize(300, 300)
le.setContentsMargins(100, 0, 0, 0)
le.setStyleSheet("background-color: cyan;")
le.setTextMargins(0, 0, 50, 50)
le.setAlignment(Qt.AlignRight | Qt.AlignBottom)
le.setDragEnabled(True)
le2 = QLineEdit(window)
le2.resize(50, 50)
le2.move(200, 0)
btn = QPushButton(window)
btn.setText("按钮")
btn.move(50, 50)
def cursor_move():
le.setCursorPosition(len(le.text()) / 2)
print(le.cursorPosition())
print(le.cursorPositionAt(QPoint(55, 105)))
le.setText("sb "*10)
le.setFocus()
le.backspace()
le.del_()
le.clear()
le.copy()
le.cut()
le.paste()
le.setSelection(2, 21)
le.selectAll()
le.setSelection(0, len(le.text()))
le.deselect()
print(le.hasSelectedText())
print(le.selectedText())
print(le.selectionStart())
print(le.selectionEnd())
print(le.selectionLength())
pass
btn.clicked.connect(cursor_move)
le.textEdited.connect(lambda val: print("文本框编辑的时候", val))
le.textChanged.connect(lambda val: print("文本框内容发生改变", val))
le.returnPressed.connect(lambda :print("回车键被按下"))
le.returnPressed.connect(lambda :le2.setFocus())
le.editingFinished.connect(lambda :print("结束编辑"))
le.cursorPositionChanged.connect(lambda old_Pos, new_Pos: print(old_Pos, new_Pos))
le.selectionChanged.connect(lambda : print("选中文本发生改变", le.selectedText()))
le.setText("xxx")
window.show()
sys.exit(app.exec_())
参考: Qt5.9中函数setAlignment()用法 Qt之拖放 Qt之QLineEdit详解(附源码) 视图中选择选中项的操作 Qt——QLineEdit使用总结 控制QLineEdit的输入范围
2.3 使用 QtDesigner 设计 GUI
1. 创建.ui 文件并使用QtDesigner完成GUI布局: Pycharm->Tools->External Tools->QTDesigner->创建窗体,选择Wdiget->拖动控件设计界面->把文件保存到项目目录下(ui格式文件)
2. 把.ui文件转换成.py文件: 右击工程中的刚才保存的.ui 文件->External Tools->pyUIc->生成.py 文件->运行.py 文件
参考: QT+SIP+Pyqt5
3 pyautogui 库 – GUI 自动化
3.1 防故障机制
为了防止 GUI 程序不受控制,在代码中添加 pyautogui.PAUSE 来让 GUI 控制暂停运行,而在 GUI 控制过程中,可启动自动防故障功能,启动该功能后,GUI 控制运行过程中将鼠标移到屏幕的左上角,程序将抛出异常而崩溃,而禁止其抛出异常的方法是加入 pyautogui.FAILSAFE = Faile
应保证在 GUI 自动控制中都启动自动放故障功能,防止 GUI 发生失控!
import pyautogui
pyautogui.PAUSE = 1
pyautogui.FAILSAFE = True
3.2 屏幕操作
计算机屏幕都以左上角为坐标原点,所有坐标都是正整数,没有负坐标;屏幕右下角为坐标最大值,其坐标值 (x,y) 根据屏幕的分辨率而定,如果屏幕分辨率为 1920*1080 ,则屏幕右下角坐标就是 (1919,1079);
获取屏幕分辨率
pyautogui.size() 返回一个列表,包含当前屏幕的像素
import pyautogui
width,height = pyautogui.size()
print(pyautogui.size())
print(width)
print(height)
运行结果:
Size(width=1920, height=1080)
1920
1080
获取屏幕快照
pyautogui.screenshot() 返回 Image 对象,可向可选参数 region 传入一个元组进行区域截图,元组内容应包括截图区域的 (x,y,宽度,高度),其中 x,y 为截图的起始坐标;pyautogui.screenshot() .getpixel() 返回 Image 对象中该坐标的像素颜色元组;
import pyautogui
im = pyautogui.screenshot()
print(im.getpixel((0,0)))
运行结果:
(255, 255, 255)
分析屏幕快照
- pyautogui.pixelMatchesColor() 返回该坐标下的颜色是否符合输入的像素颜色参数
import pyautogui
print(pyautogui.pixelMatchesColor(0,0,(255,255,255)))
运行结果:
True
3.3 控制鼠标
移动鼠标
pyautogui.moveTo() 方法可实现鼠标的定点移动,可选的 duration 参数制定了鼠标移动到目标位置所需的秒数,默认值为 0;pyautogui.moveRel() 方法相对于当前鼠标的位置而移动鼠标;
import pyautogui
pyautogui.FAILSAFE = True
pyautogui.moveTo(100, 200, duration=0.25)
pyautogui.moveRel(100,0)
获取鼠标位置
pyautogui.position() 可获得当前鼠标的位置坐标;
import pyautogui, time
while 1:
print(pyautogui.position())
time.sleep(0.5)
鼠标点击
pyautogui.click() 方法可实现鼠标的定点点击,可选关键字参数 botton= 可指定鼠标的按键,包括 left,middle,right 三个参数;pyautogui.doubleClick() 实现双击;pyautogui.rightClick() 实现右击;(完全可以用 click 代替)pyautogui.middleClick() 实现鼠标中键点击;(完全可以用 click 代替)
import pyautogui
pyautogui.click(14,1043,button='left')
pyautogui.click(14,1043,button='right')
pyautogui.doubleClick(412,391)
pyautogui.rightClick(412,391)
pyautogui.middleClick(412,391)
拖动鼠标
pyautogui.drag() 拖动鼠标到定点坐标;pyautogui.dragRel() 相对于当前鼠标的位置而拖动鼠标;
import pyautogui
pyautogui.click()
distance = 200
while distance > 0:
pyautogui.dragRel(distance,0,duration=0.2)
distance -= 5
pyautogui.dragRel(0,distance,duration=0.2)
pyautogui.dragRel(-distance,0,duration=0.2)
distance -= 5
pyautogui.dragRel(0,-distance,duration=0.2)
滚动鼠标
pyautogui.scroll() 实现鼠标向上滚动;
import pyautogui
pyautogui.scroll(200)
3.4 图像识别
识别图片在屏幕上的位置
pyautogui.locateOnScreen() 传入一个图像,返回该图像在当前屏幕上的坐标元组;pyautogui.locateCenterOnScreen() 返回区域的中心坐标pyautogui.center() 相当于以上两者的结合pyautogui.locateAllOnScreen() 定位该图片的所有坐标
import pyautogui, os
os.chdir('C:\\Users\\xxxx\\Desktop')
screenShot = pyautogui.locateOnScreen('20190829084103.png')
print(screenShot)
print(pyautogui.center(screenShot))
print(pyautogui.locateCenterOnScreen('20190829084103.png'))
for pos in pyautogui.locateAllOnScreen('20190829084103.png'):
print(pos)
print(list(pyautogui.locateAllOnScreen('20190829084103.png')))
运行结果:
Box(left=100, top=640, width=25, height=30)
Point(x=112, y=655)
Point(x=112, y=655)
Box(left=100, top=640, width=25, height=30)
Box(left=1316, top=910, width=25, height=30)
[Box(left=100, top=640, width=25, height=30), Box(left=1316, top=910, width=25, height=30)]
3.5 键盘输入
pyautogui.typewrite() 通过键盘发送一个字符串;pyautogui.keyDown() 模拟键盘按下不松pyautogui.press() 模拟敲击键盘pyautogui.keyUp() 模拟松开键盘pyautogui.hotkey() 相当于keyDown 和 keyUp 的组合,可接受多个键字符串参数,按顺序模拟按下,再按反顺序释放;
import pyautogui
pyautogui.click()
pyautogui.typewrite('Hellow world!', interval=0.5)
pyautogui.keyDown('shift')
pyautogui.press('4')
pyautogui.keyUp('shift')
pyautogui.hotkey('ctrl','c')
KEYBOARD_KEYS大全(可传入到上述函数的键值)
print(pyautogui.KEYBOARD_KEYS)
运行结果: [’\t’, ‘\n’, ‘\r’, ’ ‘, ‘!’, ‘"’, ‘#’, ‘$’, ‘%’, ‘&’, "’", ‘(’, ‘)’, ‘*’, ‘+’, ‘,’, ‘-’, ‘.’, ‘/’, ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘:’, ‘;’, ‘<’, ‘=’, ‘>’, ‘?’, ‘@’, ‘[’, ‘\’, ‘]’, ‘^’, ‘_’, ‘`’, ‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’, ‘i’, ‘j’, ‘k’, ‘l’, ‘m’, ‘n’, ‘o’, ‘p’, ‘q’, ‘r’, ‘s’, ‘t’, ‘u’, ‘v’, ‘w’, ‘x’, ‘y’, ‘z’, ‘{’, ‘|’, ‘}’, ‘~’, ‘accept’, ‘add’, ‘alt’, ‘altleft’, ‘altright’, ‘apps’, ‘backspace’, ‘browserback’, ‘browserfavorites’, ‘browserforward’, ‘browserhome’, ‘browserrefresh’, ‘browsersearch’, ‘browserstop’, ‘capslock’, ‘clear’, ‘convert’, ‘ctrl’, ‘ctrlleft’, ‘ctrlright’, ‘decimal’, ‘del’, ‘delete’, ‘divide’, ‘down’, ‘end’, ‘enter’, ‘esc’, ‘escape’, ‘execute’, ‘f1’, ‘f10’, ‘f11’, ‘f12’, ‘f13’, ‘f14’, ‘f15’, ‘f16’, ‘f17’, ‘f18’, ‘f19’, ‘f2’, ‘f20’, ‘f21’, ‘f22’, ‘f23’, ‘f24’, ‘f3’, ‘f4’, ‘f5’, ‘f6’, ‘f7’, ‘f8’, ‘f9’, ‘final’, ‘fn’, ‘hanguel’, ‘hangul’, ‘hanja’, ‘help’, ‘home’, ‘insert’, ‘junja’, ‘kana’, ‘kanji’, ‘launchapp1’, ‘launchapp2’, ‘launchmail’, ‘launchmediaselect’, ‘left’, ‘modechange’, ‘multiply’, ‘nexttrack’, ‘nonconvert’, ‘num0’, ‘num1’, ‘num2’, ‘num3’, ‘num4’, ‘num5’, ‘num6’, ‘num7’, ‘num8’, ‘num9’, ‘numlock’, ‘pagedown’, ‘pageup’, ‘pause’, ‘pgdn’, ‘pgup’, ‘playpause’, ‘prevtrack’, ‘print’, ‘printscreen’, ‘prntscrn’, ‘prtsc’, ‘prtscr’, ‘return’, ‘right’, ‘scrolllock’, ‘select’, ‘separator’, ‘shift’, ‘shiftleft’, ‘shiftright’, ‘sleep’, ‘space’, ‘stop’, ‘subtract’, ‘tab’, ‘up’, ‘volumedown’, ‘volumemute’, ‘volumeup’, ‘win’, ‘winleft’, ‘winright’, ‘yen’, ‘command’, ‘option’, ‘optionleft’, ‘optionright’]
|