PyQt5学习笔记.docx
《PyQt5学习笔记.docx》由会员分享,可在线阅读,更多相关《PyQt5学习笔记.docx(54页珍藏版)》请在冰豆网上搜索。
PyQt5学习笔记
PyQt5学习笔记
PyQt5学习笔记
这是Python3.x和PyQt5的学习教程。
大部分为我从鱼c工作室网站上的一个教程上看到的,也有一些我自己的心得与批注。
上面更为详细与具体。
目前来说PyQt的资料很少,书也只是国外人写的PyQt4的。
我自己看的就是PythonQtGUI快速编程,讲的很细致,但版本不太好。
这个差不多是最好的PyQt5教程吧,程序亲测可用。
1.1第一个窗口程序
#-*-coding:
utf-8-*-
导入模块
"""第一个程序"""
fromPyQt5importQtWidgets
importsys
Pyqt程序都有个Application对象
app=QtWidgets.QApplication(sys.argv)
first_window=QtWidgets.QWidget()
first_window.resize(400,300)//窗口大小
first_window.setWindowTitle("我的第一个程序")//标题
first_window.show()//显示图像
sys.exit(app.exec_())//事件主循环
2.5消息窗口(退出时消息提示)
#-*-coding:
utf-8-*-
"""消息窗口示例"""
importsys
fromPyQt5importQtWidgets,QtGui,QtCore
classMessageBox(QtWidgets.QWidget):
def__init__(self,parent=None):
QtWidgets.QWidget.__init__(self,parent)
self.setGeometry(300,300,250,150)
self.setWindowTitle("消息窗口演示程序")
defcloseEvent(self,event):
显示yes/no的消息窗口
reply=QtWidgets.QMessageBox.question(self,'确认退出','你确定要退出么?
',
QtWidgets.QMessageBox.Yes,
QtWidgets.QMessageBox.No)
ifreply==QtWidgets.QMessageBox.Yes:
event.accept()
else:
event.ignore()
app=QtWidgets.QApplication(sys.argv)
qb=MessageBox()
qb.show()
sys.exit(app.exec_())
如果我们关闭QWidget窗口,QCloseEvent事件就会被触发。
要改变原有的wdiget行为阻止查窗口的关闭,我们就需要重新实现closeEvent()方法。
在replay变量中,第一个字符串参数'确认退出'在消息窗口的标题栏显示。
第二个字符串参数'你确定要退出么?
'以对话的形式显示在消息窗口中。
返回的结果被保存在reply变量中。
2.6将消息放在屏幕中心
#-*-coding:
utf-8-*-
"""窗口置中"""
importsys
fromPyQt5importQtWidgets
classCenter(QtWidgets.QWidget):
def__init__(self,parent=None):
QtWidgets.QWidget.__init__(self,parent)
self.setWindowTitle("窗口置中程序")
self.resize(250,150)
self.center()
defcenter(self):
screen=QtWidgets.QDesktopWidget().screenGeometry()
size=self.geometry()
self.move((screen.width()-size.width())/2,(screen.height()-size.height())/2)
app=QtWidgets.QApplication(sys.argv)
center=Center()
center.show()
sys.exit(app.exec_())
3PyQt5中的菜单和工具栏
3.1主窗口
QMainWindow类用来创建应用程序的主窗口。
通过该类,我们可以创建一个包含状态栏、工具栏和菜单栏的经典应用程序框架
3.2状态栏
#-*-coding:
utf-8-*-
"""状态栏程序"""
importsys
fromPyQt5importQtWidgets
classMainWindow(QtWidgets.QMainWindow):
def__init__(self):
super(MainWindow,self).__init__()#继承
self.resize(250,150)
self.setWindowTitle("状态栏程序示例")
self.statusBar().showMessage("就绪")
app=QtWidgets.QApplication(sys.argv)
main_window=MainWindow()
main_window.show()
sys.exit(app.exec_())
所有的类在创建时都会先调用构造函数(python中就是__init__())将实例按照构造函数的操作先进行初始化,继承了其它类的类,在构造函数中,先要构造他的父类,在之前的程序中,我们都是直接调用父类的__init__()方法来完成父类的构造,但是有一种更安全的方法就是用关键字super来完成。
super(MainWindow,self).__init__()我们可以这样理解:
super(MainWindow,self)首先找到MainWindow的父类(就是QtWidgets.QMainWindow),然后把类MainWindow的对象self转换为类QtWidgets.QMainWindow的对象,然后“被转换”的类A对象调用自己的__init__函数。
考虑到super中只有指明子类的机制,因此,在多继承的类定义中,通常我们保留使用之前代码中的方法。
3.3菜单栏
#-*-coding:
utf-8-*-
"""菜单栏"""
importsys
fromPyQt5importQtWidgets,QtGui
classMainWindow(QtWidgets.QMainWindow):
def__init__(self):
super(MainWindow,self).__init__()
self.resize(250,150)
self.setWindowTitle("菜单栏示例")
exit_menu=QtWidgets.QAction(QtGui.QIcon(r"1.ico"),"退出",self)#菜单栏上快捷图标
exit_menu.setShortcut("Ctrl+Q")#快捷键“Ctrl+Q”
exit_menu.setStatusTip("退出程序")#状态提示文本设置为“退出程序”
exit_menu.triggered.connect(QtWidgets.qApp.quit)#信号槽连接
self.statusBar()#返回QmainWindow的QStatusBar(第一次调用时创建)
首先我们使用QMainWindow类的menuBar()方法创建一个菜单栏。
然后使用addMenu()方法添加一个菜单。
最后我们把动作对象(这里是exit_menu)添加到file菜单中。
menubar=self.menuBar()
file=menubar.addMenu("文件")
file.addAction(exit_menu)
app=QtWidgets.QApplication(sys.argv)
mainwindow=MainWindow()
mainwindow.show()
sys.exit(app.exec_())
综合示例
#-*-coding:
utf-8-*-
"""我的程序"""
importsys
fromPyQt5importQtWidgets,QtGui
classMainWindow(QtWidgets.QMainWindow):
def__init__(self):
super(MainWindow,self).__init__()
self.resize(350,250)
self.setWindowTitle("我的程序")
text_edit=QtWidgets.QTextEdit()#QTextEdit多行文本框
self.setCentralWidget(text_edit)#中心放置
exit_action=QtWidgets.QAction(QtGui.QIcon(r"sample.png"),"退出",self)#图标
exit_action.setStatusTip("退出程序")#状态提示
exit_action.setShortcut("Ctrl+Q")#快捷键
exit_action.triggered.connect(QtWidgets.qApp.quit)#信号槽连接
self.statusBar()#状态栏
self.menu_bar=self.menuBar()#菜单栏
file=self.menu_bar.addMenu("文件")#菜单栏添加“文件”
file.addAction(exit_action)#添加“文件”的相关动作
self.toolbar=self.addToolBar("退出")#工具栏
self.toolbar.addAction(exit_action)#添加工具栏的动作
app=QtWidgets.QApplication(sys.argv)
main_window=MainWindow()
main_window.show()
sys.exit(app.exec_())
4Pyqt布局管理器
布局管理器是编程中重要的一部分。
所谓布局管理是指我们在窗口中安排部件位置的方法。
布局管理有两种工作方式:
绝对定位方式(absolutepositioning)和布局类别方式(layoutclasses)。
4.1绝对定位方式
该方式下,程序员编程指定每一个部件的位置和尺寸像素。
当使用绝对定位方式时,需要注意以下几点:
·改变窗口大小时,窗口中部件的大小和位置不会随之改变。
·在不同的平台上,应用程序可能会看起来不尽相同。
·在应用程序中改变字体可能会导致布局混乱。
#-*-coding:
utf-8-*-
"""绝对定位演示"""
importsys
fromPyQt5importQtWidgets,QtGui
classMainWindow(QtWidgets.QMainWindow):
def__init__(self):
super(MainWindow,self).__init__()
self.setWindowTitle("绝对定位演示程序")
self.resize(250,150)
QtWidgets.QLabel('Couldn\'t',self).move(15,10)
QtWidgets.QLabel('care',self).move(35,40)
QtWidgets.QLabel('less',self).move(55,65)
QtWidgets.QLabel('and',self).move(115,65)
QtWidgets.QLabel('then',self).move(135,45)
QtWidgets.QLabel('you',self).move(115,25)
QtWidgets.QLabel('kiss',self).move(145,10)
QtWidgets.QLabel('me',self).move(215,10)
app=QtWidgets.QApplication(sys.argv)
main_window=MainWindow()
main_window.show()
sys.exit(app.exec_())
在该示例中,我们简单是使用move()方法来设置部件的位置。
我们通过x和y坐标来指定QLabel部件的位置,坐标起点为左上角的顶点。
x坐标从左向右增长,y坐标从上向下增长。
4.2网格布局
最通用的布局类别是网格布局(QGridLayout)。
该布局方式将窗口空间划分为许多行和列。
要创建该布局方式,我们需要使用QGridLayout类。
#-*-coding:
utf-8-*-
"""网格布局示例"""
importsys
fromPyQt5importQtWidgets
classGridLayout(QtWidgets.QMainWindow):
def__init__(self):
super(GridLayout,self).__init__()
self.setWindowTitle("网格布局演示程序")
buttton_names=['Cls','Bck','','Close',
'7','8','9','/',
按钮名
'4','5','6','*',
'1','2','3','-',
'0','.','=','+']
main_ground=QtWidgets.QWidget()
self.setCentralWidget(main_ground)#中心放置
grid=QtWidgets.QGridLayout()#网格布局
for[n,(x,y)]inenumerate([(i,j)foriinrange(5)forjinrange(4)]):
if(x,y)==(0,2):
#如果是第一行第三列
grid.addWidget(QtWidgets.QLabel(buttton_names[n]),x,y)
else:
grid.addWidget(QtWidgets.QPushButton(buttton_names[n]),x,y)
main_ground.setLayout(grid)
app=QtWidgets.QApplication(sys.argv)
grid_layout=GridLayout()
grid_layout.show()
sys.exit(app.exec_())
for循环部分,使用addWidget()方法,我们将部件加入到网格布局中。
addWidget()方法的参数依次为要加入到局部的部件,行号和列号
对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串),enumerate将其组成一个索引序列,利用它可以同时获得索引和值
最后将创建好的网格布局用setLayout方法置于之前创建的main_ground实例上,如果不创建main_ground而是直接在最后用self.setLayout(grid),程序可以正常跑起来,但是你看不到你布置好的网格布局,同时会被警告QWidget:
:
setLayout:
AttemptingtosetQLayout""onGridLayout"",whichalreadyhasalayout。
在4.2中我们直接应用self.setLayout(grid)方法将布局安放在了程序界面,这是因为我们的主程序界面继承的是QtWidgets.QWidget类而不是这节中的QtWidgets.QMainWindow类。
网格布局中可以跨越多行或多列
#-*-coding:
utf-8-*-
"""网格布局跨行示例"""
importsys
fromPyQt5importQtWidgets
classGridLayout(QtWidgets.QMainWindow):
def__init__(self):
super(GridLayout,self).__init__()
self.setWindowTitle("网格布局跨行演示程序")
main_ground=QtWidgets.QWidget()
self.setCentralWidget(main_ground)
grid=QtWidgets.QGridLayout()
grid.setSpacing(20)
grid.addWidget(QtWidgets.QLabel("标题:
"),1,0)
grid.addWidget(QtWidgets.QLineEdit(),1,1)
grid.addWidget(QtWidgets.QLabel("作者:
"),2,0)
grid.addWidget(QtWidgets.QLineEdit(),2,1)
grid.addWidget(QtWidgets.QLabel("评论:
"),3,0)
grid.addWidget(QtWidgets.QTextEdit(),3,1,5,1)#设置行列跨度行跨度设置为5,列跨度设置为1。
main_ground.setLayout(grid)
self.resize(350,300)
app=QtWidgets.QApplication(sys.argv)
grid_layout=GridLayout()
grid_layout.show()
sys.exit(app.exec_())
5PyQt5的事件和信号
5.1事件
事件(Events)是GUI程序中很重要的一部分。
它由用户或系统产生。
当我们调用程序的exec_()方法时,程序就会进入主循环中。
主循环捕获事件并将它们发送给相应的对象进行处理。
为此,奇趣公司(Trolltech)引入了一种独一无二的处理模式:
信号与槽机制。
5.2信号槽
当用户单击一个按钮,拖动一个滑块或进行其它动作时,相应的信号就会被发射。
除此之外,信号还可以因为环境的变化而被发射。
比如一个运行的时钟将会发射时间信号等。
而所谓的槽则是一个方法,该方法将会响应它所连接的信号。
在Python中,槽可以是任何可以被调用的对象。
#-*-coding:
utf-8-*-
"""信号槽示例"""
importsys
fromPyQt5importQtWidgets,QtCore
classSignalSlot(QtWidgets.QWidget):
def__init__(self):
super(SignalSlot,self).__init__()
self.setWindowTitle("信号槽演示程序")
lcd=QtWidgets.QLCDNumber(self)#数字LCD显示器
slider=QtWidgets.QSlider(QtCore.Qt.Horizontal,self)#水平滑动条
v_box=QtWidgets.QVBoxLayout()
v_box.addWidget(lcd)
v_box.addWidget(slider)
self.setLayout(v_box)
slider.valueChanged.connect(lcd.display)#信号改变会连接到槽上
self.resize(250,150)
app=QtWidgets.QApplication(sys.argv)
qb=SignalSlot()
qb.show()
sys.exit(app.exec_())
解释:
slider.valueChanged.connect(lcd.display)
这里我们将滑块的 valueChanged信号连接到 LCD 显示器的 display槽函数上。
下面介绍connect 的用法,如果信号发送者对象为emit(这里是 slider 对象),要发射的信号是signal(这里是valueChanged 信号),信号的接收者对象accept(这里是 lcd 对象),对信号做出响应的槽函数slot(这里是 display 方法),那么连接信号和槽的方法为:
emit.signal.connect(accept.slot)
5.3重写事件处理方法
#-*-coding:
utf-8-*-
"""用Esc键推出示例"""
importsys
fromPyQt5importQtWidgets,QtCore
classEscape(QtWidgets.QWidget):
def__init__(self):
super(Escape,self).__init__()
self.setWindowTitle("Esc退出演示程序")
self.resize(250,150)
按下ESC键时程序就会结束
defkeyPressEvent(self,event):
ifevent.key()==QtCore.Qt.Key_Escape:
self.close()
app=QtWidgets.QApplication(sys.argv)
escape=Escape()
escape.show()
sys.exit(app.exec_())
5.4发射信号
通过QtCore.QObject创建的对象可以发射信号。
如果我们点击按钮,就会生成一个clicked()信号
#-*-coding:
utf-8-*-
"""发射信号示例"""
importsys
fromPyQt5importQtWidgets,QtCore
我们创建一个叫做closeEmitApp()的新的信号。
这个信号在鼠标按下时产生。
classEmitSignal(QtWidgets.QWidget):
closeEmitApp=QtCore.pyqtSignal()
def__init__(self):
super(EmitSignal,self).__init__()
self.setWindowTitle("发射信号演示程序")
我们我们还得把自定义的close