PyQt5 学习笔记
程序入口
1 | if __name__ == '__main__': |
先实例化一个QApplication
,传入sys.argv
作为参数(sys.argv
是一个 list,内容为你在控制台输入的运行这个 Python 程序的命令后面的内容,一般为文件名)。
然后将创建的窗口实例化并令其显示,最后用app.exec_()
使应用重复执行,直到窗口关闭给sys.exit()
返回 ,在 Python 3 中也可以用exec()
代替exec_()
。
自定义信号
需要先导入pyqtSignal
。
1 | from PyQt5.QtCore import pyqtSignal |
然后实例化自定义信号。
1 | s = pyqtSignal() |
也可以让这个信号携带一个或多个值。
1 | s1 = pyqtSignal(int) |
还可以重载这个信号,使之接受不同种的值的组合,注意和上面的携带多个值有区别。
1 | s3 = pyqtSignal([int], [int, str]) |
如果这样的话,在将这个信号和槽连接的时候就要注明是和哪种组合的信号连接,发射信号的时候也是,如果不写,则默认是第一种。
1 | self.s3[int].connect(self.slot) |
窗口之间发射信号时,需在程序入口处连接信号和槽。
1 | #代码来源:https://pyqt5.blog.csdn.net/article/details/107573344 |
线程之间通信时,在子线程中实例化一个自定义信号对象,然后在主窗口中实例化子线程,并把子线程中的自定义信号对象和主窗口的槽函数连接就行了。
1 | #代码来源:https://pyqt5.blog.csdn.net/article/details/107573344 |
布局管理
QVBoxLayout
是垂直布局,QHBoxLayout
是水平布局,V 是 Vertical(垂直),H 是 Horizontal(水平)。
用addWidget()
方法往布局里添加控件(按先后顺序从上往下从左往右),用addLayout()
方法往布局里添加布局。
QFormLayout
是表单布局,左边一列右边一列那种,用addRow
方法从上往下添加控件。
QGridLayout
是网格布局,使用addWidget()
方法添加控件,格式为addWidget(widget, row, column, rowSpan, columnSpan)
,最后两项是长宽所占的格子数,默认为一行一列。
记得最后要self.setLayout(self.layout)
消息框
包含在QMessageBox
类中,有以下几种。
-
QMessageBox.information
信息框。 -
QMessageBox.question
问答框。 -
QmessageBox.warning
警告框。 -
QMessageBox.critical
错误框。 -
QMessageBox.about
关于框。
按钮也可以自定义,大致有以下几种。
- QMessageBox.Ok
- QMessageBox.Yes
- QMessageBox.No
- QMessageBox.Close
- QMessageBox.Cancel
- QMessage.Open
- QMessage.Save
语法结构:QMessageBox.information(QWidget, 'Title', 'Content', buttons)
示例:
1 | QMessageBox.question(self, 'Drinks?', 'Would you like some drinks?', QMessageBox.Yes | QMessageBox.No) |
如果要与消息框交互,可以用一个变量存下消息框返回的按钮。
1 | def show_messagebox(self): |
按钮
普通按钮(QPushButton)
普通按钮有标记和非标记两种状态,使用setCheckable(True)
方法将按钮变为可标记,用isCheckable()
方法判断按钮是否可标记。
当按钮标记状态发生变化时会发出toggled
信号。
用isChecked()
方法判断按钮是否标记。
单选按钮(QRadioButton)
单选按钮默认只会有一个按钮被选中。
用setChecked()
方法设置按钮是否被选中,当按钮状态发生改变时,会发出toggled
信号。
复选框(QCheckBox)
复选框最多有三种状态(选中,半选中,没选中),但默认只有两种,需要使用setTristate(True)
方法使复选框拥有第三种状态。
可使用setChecked()
或是setCheckState()
方法设置复选框状态,前者可传入True
(选中状态)或False
(没选中状态),后者可传入Qt.Checked
(选中状态),Qt.PartiallyChecked
(半选中状态)或Qt.UnChecked
(没选中状态)。
当复选框状态改变时,会发出stateChanged
信号。
checkState()
方法可获取复选框的状态,返回值为int
类, 为没选中状态, 为选中状态, 为半选中状态。
下拉框
下拉框分两种,一种是普通的QComboBox
,一种是字体下拉框QFontComboBox
,默认有很多字体。
使用addItem()
方法往下拉框里添加一个选项,addItems()
方法添加多个选项。
下拉框选项发生变化时会触发序号变化的信号currentIndexChanged
和文本变化的信号currentTextChanged
。
普通下拉框使用currentIndex()
方法获取当前选项序号(从 开始),currentText()
方法获取当前选项文本,字体下拉框使用currentFont()
方法获取当前选中的字体,可以用setFont()
将一些控件的字体改为选中的字体。
数字调节框
数字调节框分QSpinBox
和QDoubleSpinBox
,前者用于调节整型数字,后者用于调整浮点型数字。
使用setRange()
方法设置范围,默认为 ,用setSingleStep()
方法设置步长,用setDecimals()
方法设置浮点型数字调节框的小数位数,用setValue()
方法设置调节框的值,用value()
方法获得调节框的值。
当调节框内的值发生变化时,会触发valueChanged
信号。
滑动条
滑动条分垂直滑动条和水平滑动条,前者用QSlider(Qt.Horizontal, self)
实例化,后者用QSlider(Qt.Vertical, self)
。
可以用setRange()
方法设置滑动条的范围,也可以用setMinimum()
和setMaximum()
单独设置最大值和最小值。
用value()
方法获取滑动条的数值,setValue()
方法设置滑动条的数值,每当滑动条数值发生变化时,会触发valueChanged
信号。
定时器
定时器QTimer
可以定时发出timeout
信号,使用start(int)
方法使定时器开始工作并设定间隔时长,单位为毫秒,stop()
方法使其停止工作,isActive()
方法判断其是否处于激活状态。
进度条
进度条实例化后默认是水平的,可以用setOrientation(Qt.Vertical)
方法使进度条垂直显示。
设置范围的方法同滑动条。
用setValue()
方法设置进度条的值,value()
方法获得进度条的值。
用reset()
重置进度条。
组合框
使用QGroupBox(str, self)
实例化一个标题为str
的组合框 。
向QGroupBox
中添加控件的方法是先把控件放在一个布局管理器中,再使用setLayout()
方法将其放在QGroupBox
里。
1 | def layout_init(self): |
每个组合框都是一个独立的部分,各组合框中的控件互不影响。
setFlat(True)
方法可以使QGroupBox
的边框消失。
工具箱
工具箱有很多抽屉,每次只能打开一个。
使用addItem(QWidget, str)
方法添加控件,每使用一次addItem()
就多出来一个抽屉,第一个参数为要添加的控件,第二个参数为这个抽屉的名称。
当点击不同的抽屉时,会触发currentChanged
信号,使用currentIndex()
方法获取当前所点击的抽屉序号,序号从 开始。
事件处理
事件和信号不一样,不要弄混了。
当事件对象创建完毕后,会被传递给QObject
的event()
函数,再根据这个事件不同的类型分发给不同的事件处理器。
PyQt中提供了两种针对事件处理的机制:一种是信号和槽,另一种则是事件;事件处理在PyQt中是比较底层的,这里的事件常见如下类型:
键盘事件、鼠标事件、拖放事件、滚轮事件、定时事件、焦点事件、进入和离开事件(光标移入控件或者移出),移动事件(窗口位置变化),
显示和隐藏事件,窗口事件(窗口是否为当前窗口)、以及常见的Qt事件:Socket事件、剪贴板事件、文字改变事件,布局改变事件;
PyQt提供了5中事件处理和过滤方法,弱到强,其中前两者常用;
(1)重写事件具体的函数(例如:mousePressEvent()/keyPressEvent()…)
(2)重新实现QObject.event()一般用在PyQt没有提供该事件的处理函数的情况下,即添加一个新的事件;
(3)通过事件过滤器
对QObject调用installEventFilter,则相当于为QObject安装了一个事件过滤器;对于QObject的全部事件来说,他们会先传递到事件过滤函数eventFilter中;
在函数中我们可以放弃或者修改某些事件,如果该过滤事件比较多,则会降低性能;
(4)在QApplication中设置事件过滤器
这种方式比前者更强大,QApplication的事件过滤器会捕获所有QObject的事件,且第一个获得事件,即在任意一个事件过滤器之前捕获;
(5)重写QApplication中notify()方法;
使用notify方法来分发事件;想在任意事件处理器之前捕获事件,则唯一方法就是从写notify方法;
(以上文字引自https://www.cnblogs.com/ygzhaof/p/10132824.html)
第一种方法比较简单,直接重新写一个和事件同名的函数就行了。
第二种方法是重写event()
函数,在event()
函数里对需要自定义的事件进行判断并处理,最后返回QWidget.event(self, event)
,好让其他事件处理器继续处理这个事件。
1 | #在窗口中单击右键时打印 You Press Right Button.,单击左键时打印 You Press Left Button. |
第三种方法是写一个eventFilter()
函数, 内容如上,最后返回QWidget.eventFilter(self, watched, event)
,然后使用installEventFilter()
方法给控件添加事件过滤器。
1 | class Demo(QWidget): |
第四种方法和第三种类似,但不是给控件安装事件过滤器,而是直接在QApplication
中安装事件过滤器,把上面代码中安装事件过滤器的部分删掉,在程序入口处加这么一句就行。
1 | if __name__ == '__main__': |
拖放
拖放分为拖动和放下两个动作废话,它们涉及到以下事件:
dragEnterEvent
所拖动目标进入接收该事件的窗口或控件时触发。dragMoveEvent
所拖动目标进入窗口或控件后,继续被拖动时触发。dragLeaveEvent
所拖动目标离开窗口或控件时触发。dropEvent
所拖动目标被放下时触发。
使用setAcceptDrops(True)
方法让控件接收放下事件。
使用acceptProposedAction()
方法表明目标可以在控件上进行拖放动作。
使用QDropEvent.mimeData().text()
方法获取该文件的 URL 地址,也就是说这玩意前面有一个多余的 file:///,记得要去除。
1 | #代码来源:https://zhuanlan.zhihu.com/p/75622798 |
这玩意其实还挺复杂的,我只看懂了拖动文件,放两个链接在这里以后看。
https://blog.csdn.net/weixin_40301728/article/details/111601171
https://blog.csdn.net/weixin_40301728/article/details/113285997
剪贴板
使用QApplication.clipboard()
实例化一个剪贴板对象。
一个剪贴板对象有以下方法。
(图片来源:https://zhuanlan.zhihu.com/p/75622798,侵删)
列表控件,树形控件,表格控件
列表控件
QListWidget
列表控件中的每一项都是一个QListWidgetItem
,使用addItem()
方法把一个QListWidgetItem
添加进列表控件,可以传入一个QListWidgetItem
对象,也可以传入一个str
对象。
也可以使用addItems()
方法传入一个可循环对象(list
和tuple
之类的)。
使用insertItem(row, QListWidgetItem)
方法在指定行前面插入一项,序号从 开始。
使用QListWidgetItem(str)
实例化一个QListWidgetItem
对象,然后将其添加进列表控件,也可以直接在实例化时就指定父类(像这样self.item = QListWidgetItem('Item', self.list)
),这样就不用再添加了。
使用currentItem()
或currentRow()
方法获取当前选中的项,前者返回一个QListWidgetItem
对象,后者返回一个整数,代表被选中的是第几行,count()
方法获取项的数目,takeItem(row)
方法去掉一项。
树形控件
使用setColumnCount()
方法设定树形控件的列数(默认为 列),setHeaderLabel(str)
方法设置一列的标题, setHeaderLabels(list)
方法设置多列的标题(设置标题的顺序和addWidget()
方法类似,如使用两次setHeaderLabel()
方法,第一次设置第一列的标题,第二次设置第二列的标题)。
使用QTreeWidgetItem()
实例化一个QTreeWidgetItem
对象,可以在实例化时就传入父类,也可以使用addChild()
方法添加子类,使用setText(column, text)
方法设置该项的文字。
可以用setCheckState(column, CheckState)
方法让该项以复选框的形式出现,第一个参数是复选框出现在哪一列,用checkState(column)
方法获取该项某一列的复选框的选中情况, 返回值为CheckState
(即Qt.Checked
,Qt.UnChecked
和Qt.partiallyChecked
)。
当某一项被点击后,QTreeWidget
会发射itemClicked
信号,这是一个带参数的信号,参数为[QTreeWidgetItem, int]
,前者是被点击的这一项,后者是这一项的列号。
通过text(column)
方法获取某一项某一列的文字。
expandAll()
方法可以让QTreeWidget
的所有项处于打开状态,但只对调用之前实例化的项起作用。
表格控件
使用setRowCount(int)
方法设置行数,setColumnCount(int)
方法设置列数,也可以在实例化时使用QTabelWidget(row, column, parent)
直接设置。
setColumnWidth(column, width)
方法设置某一列的宽度,setRowHeight(row, height)
方法设置某一行的高度。
setHorizontalHeaderLabels()
和setVerticalHeaderLabels()
设置行和列的标题,用法同setHeaderLabels()
方法。
setShowGrid(bool)
设置是否显示表格的网格线。
使用QTableWidgetItem(str)
实例化一个单元格,用setItem(row, column, QTableWidgetItem)
方法将其添加进表格控件。
setTextAlignment()
方法用于设置单元格的文本对齐方式,可传入参数有以下几种。
列表视图,树形视图,表格视图
视图是基于模型的,有关数据的获取或存储操作都和模型有关,这种控件在处理大量数据的时候可以让程序处理得更快。列表控件,树形控件,表格控件分别是这三种视图的子类,只是为了使用时更方便快捷才有了这三种控件。
PyQt5 的模型有以下几种。
(图片来源:https://zhuanlan.zhihu.com/p/75629282,侵删)
列表视图
使用 setStringList(iterable)
方法把字符串列表添加进QStringListModel
中。
使用setModel(model)
方法给QListView
设置模型,然后这个视图就会将模型中的数据显示出来,当模型中的数据发生变化时,这个视图的显示也会变化。
使用setEditTriggers()
方法设置视图的编辑规则,可传入以下值。
使用insertRows(row, count)
方法在视图的某一行插入若干个空行,setData(QModelIndex, data)
方法给某一行设置数据,currentIndex().data()
方法可以获取选中行的数据,currentIndex.row()
方法获取选中行的序号,index(row)
方法获取指定行的QModelIndex
,行的序号从 开始。
removeRows(row, count)
方法用于移除从指定行开始的连续几行。
树形视图
树形视图通常用来显示文件目录,也就是说一般使用QDirModel
。
使用setReadOnly(bool)
方法设置是否使用只读模式,setSorting()
方法设置显示的文件和文件夹的排序方式,可传入以下参数(多个参数用竖线分开:self.model.setSorting(QDir.Name | QDir.IgnoreCase)
)。
使用树状视图的currentIndex()
方法获取选中目标的QModelIndex
,然后分别传入模型的fileName()
和filePath()
函数中,获取目标的名字和路径。
滚动区域与滚动条
众所周知,如果你实例化 个按钮,那么你的界面将会非常拥挤和丑陋,但我们可以把这 个按钮放在一个滚动区域里面,然后通过拖动滚动条来查看更多的按钮,这就是一个滚动区域。
滚动区域自带滚动条,也可以不使用自带的,自己设置滚动条。
使用horizontalScrollBar()
方法获取滚动区域的横向滚动条,返回类型为QScrollBar
,同理verticalScrollBar()
方法获取垂直滚动条,类型如上。也就是说可以这两个直接使用QScrollBar
类的方法。
用setWidget()
方法给滚动区域设置控件,setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
隐藏横向滚动条,setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
隐藏纵向滚动条。
使用QScrollBar(Qt.Horizontal, self)
实例化一个水平滚动条,QScollBar(Qt.Vertical, self)
实例化一个垂直滚动条。
使用setMaxinmum(int)
方法设置滚动条的最大值,maximum()
获取滚动条的最大值。
使用setValue(int)
方法设置滚动条的值,value()
方法获取滚动条的值。
对话框
颜色和字体对话框
使用QColorDialog.getColor()
方法显示颜色对话框,其返回值为QColor
,可以使用setTextColor(QColor)
方法设定控件中文字的颜色。如果在颜色对话框中选择了取消,则返回值为无效值,可以使用isValid()
方法判断其是否有效。
使用QFontDialog.getFont()
方法显示字体对话框,返回两个值,类型分别是QFont
和bool
,后者表示在字体对话框中是否按下了确认按钮,使用setFont(QFont)
方法设置控件中文字的字体。
输入对话框
输入对话框有以下几种输入方式。
(图片来源:https://zhuanlan.zhihu.com/p/75631812,侵删)
除getItem
以外,其他四种使用方法大致相同,需要依次次传入三个参数,如QInputDialog.getInt(self, 'Int input', 'Please input an interger.')
,即父类,标题,提示信息。而getItem
不仅需要传入这三个参数,还需要传入要加入的选项内容,最初显示的选项和选项内容是否可编辑,如QInputDialog.getItem(self, 'Choose your gender', 'Please choose your gender', [Male, Female], 0, False)
,显示一个下拉框,有两个选项,默认选项为 Male,选项不可编辑。
这五种对话框都会返回两个值,分别是输入内容和是否点击了确认按钮,需要注意的是getInt()
和getDouble()
返回的都是数,如果要将其设置为某个控件的内容的话,要用str()
函数将其转化为字符串。
文件对话框
常用的文件对话框有以下几种。
名称 | 作用 |
---|---|
getExistingDirectory | 获取文件夹 |
getOpenFileName | 获取本地文件 |
getOpenFileNames | 获取一个或多个本地文件 |
getSaveFileName | 保存本地文件 |
除getExistingDirectory()
以外,其他三个函数一般需要传入四个值,分别是父类,对话框标题,对话框打开时显示的路径,和文件扩展名过滤器,getExistingDirectory()
不需要传入文件扩展名过滤器。
文件扩展名过滤器需要包含诸如*.txt
,*.png
这类东西,如Images (*.jpg *.png *.bmp)
,如果需要使用不同的过滤器,可以在两个过滤器之间加上;;
。
文件对话框返回值为一个绝对路径和一个扩展过滤器,后者一般用不到。
主窗口
主窗口有以下组成部分。
(图片来源:https://blog.csdn.net/qq_41879343/article/details/100058795,侵删)
通过setCentralWidget()
方法可以设置主窗口的中央空间。
菜单栏
通过menubar().addmenu(title)
方法添加菜单,addAction(QAction)
方法向菜单中添加菜单项,addSeparator()
添加一根分割线。
在 PyQt5 中,菜单项和工具条都是QAction
类。
QAction
使用setIcon(QIcon)
方法给动作添加图标,setShortcut(shortcut)
方法添加快捷键,setToolTip(tip)
方法给动作添加提示,即当你把鼠标悬停在动作上方时,会有一个小气泡提示,setStatusTip(tip)
方法设置状态栏信息,当鼠标悬停在该动作上方时,状态栏会显示相应的信息。
点击动作时,会发出triggered
信号。
工具栏
工具栏上可以有多个工具条,每个工具条内可以有多个动作,使用addToolBar()
方法添加一个工具条,并返回这个工具条对象,使用addAction(QAction)
方法在工具条内添加动作。
工具条是可移动的,可以用setAllowAreas()
方法设置其可停靠区域,包括以下几种。
-
Qt.LeftToolBarArea
停靠在左侧。 -
Qt.RightToolBarArea
停靠在右侧。 -
Qt.TopToolBarArea
停靠在顶部。 -
Qt.BottomToolBarArea
停靠在底部。 -
Qt.AllToolBarAreas
以上四个位置都可停靠。
多个可停靠区域之间使用竖线隔开。
状态栏
状态栏只能有一个,使用statusBar()
方法获取状态栏对象,通过showMessage(message)
使其显示信息。
statusBar()
方法至少要调用一次,否则主窗口将不会显示状态栏(别问为什么,我也不知道)。
不同窗口
拆分窗口
使用addWidget(QWidget)
方法向QSplitter
中添加控件,每个控件各自占一个窗口,insertWidget(pos, QWidget)
用于插入一个控件,setSizes(iterable)
方法设置每个控件的宽度(如果是垂直分布的就是高度),count()
方法获取控件数量。
拆分窗口默认水平分布,如果要垂直分布,可以使用setOrientation(Qt.Vertical)
方法。
标签页窗口
标签页窗口通过addTab(QWidget, title)
方法添加标签页,每个标签页相当于一个独立的部分,使用currentIndex()
方法获取当前标签页的索引。
切换标签页时,会触发currentChanged
信号。
removeTab(index)
方法可以删除某个标签页。
堆叠窗口
堆叠窗口跟标签页窗口思路类似,都是把一个部件作为一个整体放到窗口的某个部分中。
使用addWidget(QWidget)
方法添加堆叠层,setCurrentIndex(int)
方法设置当前显示的堆叠层,堆叠层的序号从 开始。
其他内容
resize(int, int)
方法用于设定窗口大小,单位是像素。
setPlaceholderText(str)
方法用于设定 Place Holder。
setEnabled(bool)
方法用于设定按钮是否可用。
QDialog
对话框类有exec_()
方法,使用该方法打开的窗口是模态的,也就是只有关闭当前这个窗口才能操作其他窗口,而show()
方法是非模态的。只有QDialog
类有这个方法,QWidget
和QMainWindow
没有。
setEchoMode()
方法用于设定QLineEdit
显示内容的方式,有以下几种值。
QLineEdit.Normal
默认模式,显示你输入的内容,也可以直接用 表示(以此类推)。QLineEdit.NoEcho
什么也不显示。QLineEdit.Password
输入的值显示为小圆点。QLineEdit.PasswordEchoOnEdit
输入的值一开始正常显示,切换到别的输入框时变为显示小圆点,即使重新回到这个输入框也不变回原来的内容。
text()
方法用于获取QLineEdit
的内容,toPlainText()
方法用于获取QTextEdit
的内容。
setText(str)
方法用于在QLineEdit
或QTextEdit
或QTextBrowser
上显示内容。
setWindowTitle(str)
方法用于设置窗口标题,setWindowIcon(QIcon)
方法用于设置窗口图标。
setFixedSize(int, int)
方法用于固定窗口或控件大小,单位为像素。
如果要在QLabel
里显示图片,需要使用setPixmap()
方法传入一个QPixmap
对象。
如果要连接带参数的槽函数,需要使用 lambda 表达式。
可以用move(int, int)
方法把窗口移到屏幕坐标为 的地方,resize(int, int)
方法设置窗口大小,也可以用setGeometry(x, y, width, height)
方法一次性完成。
setScaledContents(bool)
方法可以让QLabel
控件里的内容随控件大小的变化而变化,即自适应。
文本编辑框的textCursor()
方法可以获取到文本编辑框当前的指针(类型为QTextCursor
),使用selection()
方法可以获取到选择的文本,removeSelectedText()
方法删去选择的文本。
deleteLater()
方法可以删除一个控件。
moveCursor(QTextCursor.End)
可以使浏览框的滑动条滑动到最底部。