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)可以使浏览框的滑动条滑动到最底部。












