高级组件
PyQt5
除了常用控件外,还有一些关于进度、展示数据等的高级控件
进度条类控件
进度条类控件主要显示任务的执行进度,PyQt5
提供了进度条控件和滑块控件这两种类型的进度条控件。其中,进度条控件是我们通常所看到的进度条,用ProgressBar
控件表示
ProgressBar
ProgressBar
控件表示进度条,通常在执行长时间任务时,用进度条告诉用户当前的进展情况。
ProgressBar
控件对应PyQt5
中的QProgressBar
类,它其实就是QProgressBar
类的一个对象
ProgressBar
继承自QWidget
类
功能作用
创建控件
QProgressBar(self)
具体形式:pb = QProgressBar(self)
一开始创建的控件是没有展示进度的,需要后续的设置
设置范围和当前值
API | 描述 |
---|---|
setMinimum(int) | 设置进度条的最小值,默认值为0 |
setMaximum(int) | 设置进度条的最大值,默认为100 |
setRange(int, int) | 设置显示的值域范围 |
setValue(int) | 设置当前值 |
reset() | 重置进度条 |
value() | 获取当前的数值 |
注意:如果设置最大值和最小值如果都是0, 则进入繁忙提示(进度条一直在滑动)
格式设置
除了进度条部分外,其控件还有一个字符串来显示进度,默认是以百分比形式的,格式设置主要设置文本的展示内容和格式字符串的对齐方式
API | 描述 |
---|---|
setFormat(str) | 设置展示字符的格式,其中参数:%p:百分比;%v:当前值;%m:总值 |
resetFormat() | 重置字符格式,变回之前的默认情况,即百分比形式 |
setAlignment(Qt.AlignmentFlag) | 设置格式字符对齐方式(设置字符串的位置格式)有水平和垂直两种,分别如下:水平对齐方式:Qt.AlignLeft :左对齐;Qt.AlignHCenter :水平居中对齐;Qt.AlignRight :右对齐;Qt.AlignJustify :两端对齐;垂直对齐方式:Qt.AlignTop :顶部对齐;Qt.AlignVCenter :垂直居中;Qt.AlignBottom :底部对齐 |
文本操作
API | 描述 |
---|---|
setTextVisible(bool) | 设置文本标签是否显示,默认是True |
text() | 获取文本内容 |
setTextDirection(QProgressBar.Direction) | 设置文本方向,仅仅对于垂直进度条有效,其中枚举值为:QProgressBar.TopToBottom :从上到下;QProgressBar.BottomToTop :从下到上 |
设置进度条方向
通过setOrientation(Qt.Orientation)
方法设置进度条的方向,默认情况下是水平方向
其中参数Qt.Orientation
有以下的枚举值:Qt.Horizontal
:设置进度条水平;Qt.Vertical
:设置进度条垂直
修改的仅仅是方向,控件的尺寸需要自己调节,这样才能更好的进行展示
倒立外观
对于水平方向的进度条,滑动方向是从左往右的,对于垂直方向,滑动方向是从下往上的
若想其滑动方向变为从右往左和从上往下,可以通过setInvertedAppearance(True)
方法进行设置翻转
其他方法
API | 描述 |
---|---|
setLayoutDirection() | 设置进度条的布局方向,支持以下3个方向值:Qt.LeftToRight :从左至右;Qt.AlignHCenter :水平居中对齐;Qt.LayoutDirectionAuto :跟随布局方向自动调整 |
setProperty() | 对进度条的属性进行设置,可以是任何属性,如self.progressBar.setProperty("value", 24) |
相关信号
API | 描述 |
---|---|
valueChanged(int) | 值发生改变时发射信号 |
案例--进度条1秒加1
创建进度条控件,让其以1秒递增1,按钮可以控制进度条停止和开始,点击stop,进度条就会停止增加
代码中使用的QBasicTimer
类是QtCore
模块中包含的一个类,主要用来为对象提供定时器事件。QBasicTimer
定时器是一个重复的定时器,除非调用stop()
方法,否则它将发送后续的定时器事件。启动定时器使用start()
方法,该方法有两个参数,分别为超时时间(毫秒)和接收事件的对象,而停止定时器使用stop()
方法即可。
表格
表格与树可以使一个控件中有规律地呈现更多数据,PyQt
提供了两种控件类用于解决该问题,一种是表格结构的控件类;另一个是树型结构的控件类。
QTableView
一个应用要和一批数据(数组、列表)进行交互,然后以表格的形式输出这些信息,就要使用QTableView
类,QTableView
类可以使用自定义的数据模型来显示内容,通过setModel来绑定数据。QTableWidget
继承自QTableView
,QTableWidget
只能使用标准的数据模型,其单元格数据通过QTableWidgetItem
对象来实现。
QTableView
控件可以绑定一个模型数据用来更新控件上的内容,可用的模式:
名称 | 含义 |
---|---|
QStringListModel | 存储一组字符串 |
QStandardItemModel | 存储任意层次结构的数据 |
QFileSystemModel | 存储本地系统的文件和目录信息(针对当前项目) |
QDirModel | 对文件系统进行封装 |
QSqlQucryModel | 对SQL 的查询结果进行封装 |
QSqlTableModel | 对SQL 中的表格进行封装 |
QSqlRelationalTableModel | 对带有foreign key 的SQL 表格进行封装 |
QSortFilterProxyModel | 对模型中的数据进行排序或过滤 |
案例--QTableView
的使用
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class Table(QWidget):
def __init__(self, arg=None):
super(Table, self).__init__(arg)
self.setWindowTitle("QTableView表格视图控件的例子")
self.resize(500,300);
self.model=QStandardItemModel(4,4); # 创建表存储任意层次结构的数据,表格是4*4的
self.model.setHorizontalHeaderLabels(['标题1','标题2','标题3','标题4']) # 创建列标题
self.model.setVerticalHeaderLabels(['数据1', '数据2', '数据3', '数据4']) # 创建行标题
for row in range(4):
for column in range(4):
item = QStandardItem("row %s, column %s"%(row,column)) # 添加数据
self.model.setItem(row, column, item)
self.tableView=QTableView()
self.tableView.setModel(self.model)
dlgLayout=QVBoxLayout();
dlgLayout.addWidget(self.tableView)
self.setLayout(dlgLayout)
if __name__ == '__main__':
app = QApplication(sys.argv)
table = Table()
table.show()
sys.exit(app.exec_())
程序运行结果:其表格的每一列/行可以自由拉动
要想固定每行/列的大小,使其不能被鼠标拉动,需要进行以下设置:
# 下面代码让表格100填满窗口
self.tableView.horizontalHeader().setStretchLastSection(True)
self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
程序运行结果如下:我们不能再用鼠标去拉动单元格的大小
添加数据:
self.model.appendRow([QStandardItem("row %s, column %s"%(11,11)),
QStandardItem("row %s, column %s"%(22,22)),
QStandardItem("row %s, column %s"%(33,33)),
QStandardItem("row %s, column %s"%(44,44)),
])
程序运行结果如下:在第五行进行了一个数据的添加
删除数据:
删除当前选中的数据:
indexs = self.tableView.selectionModel().selection().indexes() #获取当前选中的所有行
if len(indexs) > 0:
index = indexs[0] #获取第一行索引,第一行,索引为0
self.model.removeRows(index.row(), 1)
QListView
QListView
用于展示数据,它的子类是QListWidget
,QListView
是基于模型(Model
)的,需要用程序建立模型,再保存数据。
QListWidget
是一个升级版本的QListView
,它建立了一个数据存储模型(QListWidgetItem
),直接调用addItem函数,就可以调用条目item
QListView
类中的常用方法:
方法 | 描述 |
---|---|
setModel() | 用来设置View 所关联的Model ,可以使用Python 原生的list作为数据源Model |
selectedItem() | 选中Model 中的条目 |
isSelected() | 判断Model 中的某条目是否被选中 |
QListView
类中常用的信号:
信号 | 含义 |
---|---|
clicked | 当单击某项时,信号被发射 |
doubleClicked | 当双击某项时,信号被发射 |
案例--QListView
的使用
单击QListView
控件里Model中的一项时弹出消息框用来提示选择了哪一项
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import QApplication, QWidget , QVBoxLayout , QListView, QMessageBox
from PyQt5.QtCore import QStringListModel
import sys
class ListViewDemo(QWidget):
def __init__(self, parent=None):
super(ListViewDemo, self).__init__(parent)
self.setWindowTitle("QListView 例子")
self.resize(300, 270)
layout = QVBoxLayout()
# 创建QListView
listView = QListView()
slm = QStringListModel(); # 设置为存储一组字符串的模式
self.qList = ['Item 1','Item 2','Item 3','Item 4' ]
slm.setStringList(self.qList)
listView.setModel(slm) # 设置View所关联的Model
listView.clicked.connect(self.clicked) # 点击时发射信号,连接槽函数
layout.addWidget(listView)
self.setLayout(layout)
def clicked(self, qModelIndex):
QMessageBox.information(self, "QListView", "你选择了: "+ self.qList[qModelIndex.row()])
if __name__ == "__main__":
app = QApplication(sys.argv)
win = ListViewDemo()
win.show()
sys.exit(app.exec_())
QListWidget
QListWidget
类是一个基于条目的接口,用于从列表中添加或删除条目。列表中的每个条目都是一个QListWidgetltem
对象。QListWidget
可以设置为多重选择。
QListWidget
类中常用的方法:
方法 | 描述 |
---|---|
addltem() | 在列表中添加QListWidgetltem 对象或字符串 |
addltems() | 添加列表中的每个条目 |
insertltem() | 在指定的索引处插入条目 |
clear() | 删除列表的内容 |
setCurrentltem() | 设置当前所选条目 |
sortltems() | 按升序重新排列条目 |
QListWidget
类中常用的信号:
信号 | 含义 |
---|---|
currentltemChanged | 当列表中的条目发生改变时发射此信号 |
itemClicked | 当点击列表中的条目时发射此信号 |
案例--QListWidget
的使用
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class ListWidget(QListWidget):
def clicked(self,item):
QMessageBox.information(self, "ListWidget", "你选择了: "+item.text())
if __name__ == '__main__':
app = QApplication(sys.argv)
listWidget = ListWidget()
listWidget.resize(300,120)
listWidget.addItem("Item 1");
listWidget.addItem("Item 2");
listWidget.addItem("Item 3");
listWidget.addItem("Item 4");
listWidget.setWindowTitle('QListwidget 例子')
listWidget.itemClicked.connect(listWidget.clicked)
listWidget.show()
sys.exit(app.exec_())
QTableWidget
QTableWidget
是常用的显示数据表格的控件,QTableWidget
是QTableView
的子类, 它使用标准的数据模型,并且其单元格数据是通过QTableWidgetltem
对象来实现的。
使用QTableWidget
时需要QTableWidgetltem
,用来表示表格中的一个单元格,整个表格是用各单元格构建的。
QTableWidget
类中的常用方法:
方法 | 描述 |
---|---|
setRowCount(int row) | 设置QTableWidget 表格控件的行数 |
setColumnCount(int col) | 设置QTableWidget 表格控件的列数 |
setHorizontalHeaderLabels() | 设置QTableWidget 表格控件的水平标签 |
setVerticalHeaderLabels() | 设置QTableWidget 表格控件的垂直标签 |
setItem(int, int, QTableWidgetItem) | 在QTableWidget 表格控件的每个选项的单元空间里添加控件 |
horizontalHeader() | 获得QTableWidget 表格控件的表格头,以便执行隐藏 |
rowCount() | 获得QTableWidget 表格控件的行数 |
columnCount() | 获得QTableWidget 表格控件的列数 |
setEditTriggers(EditTriggers triggers) | 设置表格是否可编辑。设置编辑规则的枚举值 |
setSelectionBehavior | 设置表格的选择行为 |
setTextAlignment() | 设置单元格内文字的对齐方式 |
setSpan(int row, int column, int rowSpanCount, int columnSpanCount) | 合并单元格,要改变单元格的第row 行第column 列,要合并rowSpanCount 行数和columnSpanCount 列数:row :要改变的单元格行数;column :要改变的单元格列数;rowSpanCount :需要合并的行数;columnSpanCount :需要合并的列数 |
setShowGrid() | 在默认情况下,表格的显示是有网格线的:True :显示网格线;False :不显示网格线 |
setColumn Width(int column, int width) | 设置单元格行的宽度 |
setRowHeight(int row, int height) | 设置单元格列的高度 |
编辑规则的枚举值类型:
选项 | 值 | 描述 |
---|---|---|
QAbstractltemView.NoEditTriggers0No | 0 | 不能对表格内容进行修改 |
QAbstractItemView.CurrentChanged1Editing | 1 | 任何时候都能对单元格进行修改 |
QAbstractltemView.DoubleClicked2Editing | 2 | 双击单元格 |
QAbstractItemView.SelectedClicked4Editing | 4 | 单击已选中的内容 |
QAbstractItemView.EditKeyPressed8Editing | 8 | 当修改键被按下时修改单元格 |
QAbstractItemView.AnyKeyPressed16Editing | 16 | 按任意键修改单元格 |
QAbstractltemView.AllEditTriggers31Editing | 31 | 包括以上所有条件 |
表格的选择行为枚举值类型:
选项 | 值 | 描述 |
---|---|---|
QAbstractItemView.SelectItems0Selecting | 0 | 选中单个单元格 |
QAbstractItemView.SelectRows1Selecting | 1 | 选中一行 |
QAbstractItemView.SelectColumns2Selecting | 2 | 选中一列 |
单元格文本的水平对齐方式:
选项 | 描述 |
---|---|
Qt.AlignLeft | 将单元格的内容沿单元格的左边缘对齐 |
Qt.AlignRight | 将单元格的内容沿单元格的右边缘对齐 |
Qt.AlignHCenter | 在可用空间中,居中显示在水平方向上 |
Qt.AlignJustify | 将文本在可用空间中对齐,默认是从左到右的 |
单元格文本的垂直对齐方式:
选项 | 描述 |
---|---|
Qt.AlignTop | 与顶部对齐 |
Qt.AlignBotom | 与底部对齐 |
Qt.AlignVCenter | 在可用空间中,居中显示在垂直方向上 |
Qt.AlignBaseline | 与基线对齐 |
案例--QTableWidget
的使用
在控件中显示的数据是可编辑的:
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import * # 主要的是QColor和QBrush,用于单元格字体颜色
class Table(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle("QTableWidget 例子")
self.resize(430,230);
conLayout = QHBoxLayout()
#self.table = QTableWidget(4, 3) # 构造了一个QTableWidget对象,并设置了表格为4行3列
# 构造表格,初始化QTableWidget的实例化对象,生成一个4行3列的表格
tableWidget = QTableWidget()
tableWidget.setRowCount(4)
tableWidget.setColumnCount(3)
#tableWidget.setColumnCount(4) # 添加图片用到的4*4的表格
conLayout.addWidget(tableWidget)
# 设置表格头,要在初始化行号和列号之后,否则是没有效果的
tableWidget.setHorizontalHeaderLabels(['姓名','性别','体重(kg)']) # 设置了水平表格头
#tableWidget.setHorizontalHeaderLabels(['姓名','性别','体重(kg)','图片']) # 添加图片设置的水平表格头
tableWidget.setVerticalHeaderLabels(['行1', '行2', '行3', '行4']) # 设置了垂直表格头
# 设置表格头为伸缩模式,使用时要将设置垂直表格头该行代码禁用
#tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
#tableWidget.setSpan(0,0,3,1) # 用于合并单元格,将表格第一行第一列(0,0)的单元格,改为占据3行1列(3,1)
newItem = QTableWidgetItem("张三") # 生成了一个QTableWidgetItem对象,名称为张三,生成的单元格加载到0行0列处
#newItem.setForeground(QBrush(QColor(255,0,0))) # 设置单元格中的字体为红色
#newItem.setFont(QFont("Times", 12, QFont.Black)) # 将字体加粗
#newItem.setFont(QFont("Times", 12, QFont.Black)) # 设置字体处于右下方,方法一
#newItem.setTextAlignment( Qt.AlignRight| Qt.AlignBottom )# 设置字体处于右下方,方法二
tableWidget.setItem(0, 0, newItem)
#设置单元格大小
#tableWidget.setColumnWidth(0, 150) # 将第一列的单元格宽度设置为150,0表示第一
#tableWidget.setRowHeight(0, 120) # 将第一行的单元格高度设置为150,0表示第一
'''
newItem = QTableWidgetItem("男")
tableWidget.setItem(0, 1, newItem)
newItem = QTableWidgetItem("160")
tableWidget.setItem(0, 2, newItem)
'''
'''
newItem = QTableWidgetItem(QIcon("./images/bao1.png"), "背包") # 添加图片,并显示其描述信息:背包
tableWidget.setItem(0, 3, newItem)
'''
'''
# 在单元格中放置控件,来代替上述“男”,“160”的单元格,放入下拉单选框控件
comBox = QComboBox()
comBox.addItem("男")
comBox.addItem("女")
comBox.setStyleSheet("QComboBox{margin:3px};")
tableWidget.setCellWidget(0,1,comBox)
# 放置按钮控件
searchBtn = QPushButton("修改")
searchBtn.setDown( True )
searchBtn.setStyleSheet("QPushButton{margin:3px};")
tableWidget.setCellWidget(0, 2, searchBtn)
'''
# 将表格变为禁止编辑,默认情况下,表格中的字符串是可以更改的,双击一个单元格,就可以在上面修改,若想要只读,执行下面代码
#tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
# 设置表格为整行选择,表格默认选中的是单个单元格,以下代码可以使整行选中
#tableWidget.setSelectionBehavior( QAbstractItemView.SelectRows)
# 将行和列的宽度,高度设为与内容的宽度,高度相匹配,与设置表格头为伸缩模式该行代码不能同时使用
#tableWidget.resizeColumnsToContents()
#tableWidget.resizeRowsToContents()
# 表格表头的显示与隐藏,使用下面两行代码这隐藏行列表格头
#tableWidget.verticalHeader().setVisible(False)
#tableWidget.horizontalHeader().setVisible(False)
# 不显示表格单元格的分割线,单元格不再有线划分
#tableWidget.setShowGrid(False)
self.setLayout(conLayout)
if __name__ == '__main__':
app = QApplication(sys.argv)
example = Table()
example.show()
sys.exit(app.exec_())
在表格中快速定位到指定行
当表格的行数很多时,可以通过输入行号进行直接的定位并显示,输入10,就直接显示到第10行,定位一般通过标注颜色或选中单元格来使其凹显,一般情况这两个选择一个使用即可。
text = "(10,1)" # 查找第11行第二列的单元格
items = tableWidget.findItems(text, QtCore.Qt.MatchExactly) # 遍历表格
item = items[0]
# 选中单元格
#item.setSelected( True)
# 设置单元格的背景颜色为红色
item.setForeground(QBrush(QColor(255, 0, 0)))
row = item[0].row() # 获取其行号
self.tableWidget.verticalScrollBar().setSliderPosition(row) # 模拟鼠标滚轮快速定位到指定行,这样定位的行就在表格的上方
设置单元格的排序方式
要想对单元格内进行升/降序排列,需要先导入PyQt5.QtCore
模块中的Qt
类
from PyQt.QtCore import Qt
#Qt.DescendingOrder 降序
#Qt.AscendingOrder 升序
tableWidget.sortItems(2, QtCore.Qt.DescendingOrder) # 以第三列的数据设置降序,2表示第三列
改变单元格中显示的图片大小
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class Table(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle("QTableWidget 例子")
self.resize(1000,900);
conLayout = QHBoxLayout()
#创建表格3*5
table= QTableWidget()
table.setColumnCount(3)
table.setRowCount(5)
table.setHorizontalHeaderLabels(['图片1','图片2','图片3'])
table.setEditTriggers(QAbstractItemView.NoEditTriggers)
table.setIconSize(QSize(300,200)); # 设置图片的大小
for i in range(3): # 让单元格列宽和图片相同
table.setColumnWidth(i, 300)
for i in range(5): # 让单元格行高和图片相同
table.setRowHeight(i, 200)
# 批量的添加图片
for k in range(15):
i = k/3
j = k%3
item = QTableWidgetItem()
item.setFlags(Qt.ItemIsEnabled) # 用户点击时表格时,图片被选中
icon = QIcon(r'.\images\bao%d.png' % k)
item.setIcon(QIcon(icon ) )
print('e/icons/%d.png i=%d j=%d' %( k , i , j ) )
table.setItem(i,j,item)
conLayout.addWidget(table)
self.setLayout(conLayout)
if __name__ == '__main__':
app = QApplication(sys.argv)
example = Table()
example.show()
sys.exit(app.exec_())
获得单元格的内容
tableWidget.itemClicked.connect(self.handleItemClick)
# 槽函数
def getItem(self, item):
print("你选择的=>" + item.text())
支持右键菜单
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import ( QMenu , QPushButton, QWidget, QTableWidget, QHBoxLayout, QApplication, QTableWidgetItem, QHeaderView)
from PyQt5.QtCore import QObject, Qt
class Table( QWidget ):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle("QTableWidget 例子")
self.resize(500,300);
conLayout = QHBoxLayout()
self.tableWidget= QTableWidget()
self.tableWidget.setRowCount(5)
self.tableWidget.setColumnCount(3)
conLayout.addWidget(self.tableWidget )
self.tableWidget.setHorizontalHeaderLabels(['姓名','性别','体重' ])
self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
newItem = QTableWidgetItem("张三")
self.tableWidget.setItem(0, 0, newItem)
newItem = QTableWidgetItem("男")
self.tableWidget.setItem(0, 1, newItem)
newItem = QTableWidgetItem("160")
self.tableWidget.setItem(0, 2, newItem)
# 表格中第二行记录
newItem = QTableWidgetItem("李四")
self.tableWidget.setItem(1, 0, newItem)
newItem = QTableWidgetItem("女")
self.tableWidget.setItem(1, 1, newItem)
newItem = QTableWidgetItem("170")
self.tableWidget.setItem(1, 2, newItem)
self.tableWidget.setContextMenuPolicy(Qt.CustomContextMenu) # 允许右键产生子菜单
self.tableWidget.customContextMenuRequested.connect(self.generateMenu) # 右键菜单
self.setLayout(conLayout)
def generateMenu(self,pos):
#rint( pos)
row_num = -1
for i in self.tableWidget.selectionModel().selection().indexes():
row_num = i.row()
if row_num < 2 :
menu = QMenu()
item1 = menu.addAction(u"选项一")
item2 = menu.addAction(u"选项二")
item3 = menu.addAction(u"选项三" )
action = menu.exec_(self.tableWidget.mapToGlobal(pos))
if action == item1:
print( '您选了选项一,当前行文字内容是:',self.tableWidget.item(row_num,0).text(),self.tableWidget.item(row_num,1).text() ,self.tableWidget.item(row_num,2).text())
elif action == item2:
print( '您选了选项二,当前行文字内容是:',self.tableWidget.item(row_num,0).text(),self.tableWidget.item(row_num,1).text() ,self.tableWidget.item(row_num,2).text() )
elif action == item3:
print( '您选了选项三,当前行文字内容是:', self.tableWidget.item(row_num,0).text(),self.tableWidget.item(row_num,1).text() ,self.tableWidget.item(row_num,2).text() )
else:
return
if __name__ == '__main__':
app = QApplication(sys.argv)
example = Table()
example.show()
sys.exit(app.exec_())
树
QTreeView
QTreeView
类实现了树型结构,和目录类似,具有分层结构,一级二级标题。
树型结构是通过QTreeWidget
和QTreeWidgetItem
类实现的,其中QTreeWidgetItem
类实现了节点的添加。
QTreeWidget
类中的常用方法:
方法 | 描述 |
---|---|
setColumnWidth(int column, int width) | 将指定列的宽度设置为给定的值:Column ,指定的列;Width ,指定列的宽度 |
insertTopLevelItems() | 在视图的顶层索引中插入项目列表 |
expandAll() | 展开所有的树形节点 |
invisibleRootItem() | 返回树形控件中不可见的根选项(Root Item ) |
selectedltems() | 返回所有选定的非隐藏项目的列表 |
QTreeWidgetItem
类中的常用方法:
方法 | 描述 |
---|---|
addChild() | 将子项追加到子列表中 |
setText() | 设置显示的节点文本 |
Text() | 返回显示的节点文本 |
setCheckState(column, state) | 设置指定列的选中状态:Qt.Checked ,节点选中;Qt.Unchecked ,节点未选中 |
sctIcon(column, icon) | 在指定的列中显示图标 |
案例--QTreeWidget
的使用
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon , QBrush , QColor
from PyQt5.QtCore import Qt
class TreeWidgetDemo(QMainWindow):
def __init__(self,parent=None):
super(TreeWidgetDemo,self).__init__(parent)
self.setWindowTitle('TreeWidget 例子')
self.tree = QTreeWidget()
self.tree.setColumnCount(2) # 设置列数
self.tree.setHeaderLabels(['Key','Value']) # 设置头的标题
# 设置根节点,最底层的节点
root= QTreeWidgetItem(self.tree)
root.setText(0,'root')
root.setIcon(0,QIcon("./images/root.png"))
self.tree.setColumnWidth(0, 160) # 设置列宽
# 设置节点的背景颜色
#brush_red = QBrush(Qt.red)
#root.setBackground(0, brush_red)
#brush_green = QBrush(Qt.green)
#root.setBackground(1, brush_green)
# 设置子节点1
child1 = QTreeWidgetItem(root) # 其上一级为root
child1.setText(0,'child1')
child1.setText(1,'ios')
child1.setIcon(0,QIcon("./images/IOS.png"))
child1.setCheckState(0, Qt.Checked) # 设置节点状态,使用setCheckState()函数设置节点是否为选中状态
# 设置子节点2
child2 = QTreeWidgetItem(root)
child2.setText(0,'child2')
child2.setText(1,'')
child2.setIcon(0,QIcon("./images/android.png"))
# 设置子节点3
child3 = QTreeWidgetItem(child2)
child3.setText(0,'child3')
child3.setText(1,'android')
child3.setIcon(0,QIcon("./images/music.png"))
self.tree.addTopLevelItem(root)
self.tree.expandAll() # 结点全部展开
self.setCentralWidget(self.tree)
if __name__ == '__main__':
app = QApplication(sys.argv)
tree = TreeWidgetDemo()
tree.show()
sys.exit(app.exec_())
除了上述方法,还可以通过QTreeWidget.insertToplevelItems()
的方法来实现树形结构:
self.tree = QTreeWidget()
self.tree.setcolumncount(2) # 设置列数
self.tree.setHeaderLabels(['Key', 'Value']) # 设置树形控件头部的标题
# 设置根节点
root= QTreeWidgetItem()
root.setText{0,"root")
rootList = []
rootList.append(root)
# 设置树形控件的子节点1
childl = QTreeWidgetItem()
childl.setText(0, 'child1')
child1.setText(l, 'ios')
root.addChild(childl)
self.tree.insertToplevelItems(0, rootList)
案例--给节点添加响应事件
使用树型控件时触发树型节点的响应事件,关键是建立信号和槽函数进行连接。
from PyQt5.QtWidgets import *
import sys
class TreeWidgetDemo(QMainWindow):
def __init__(self,parent=None):
super(TreeWidgetDemo,self).__init__(parent)
self.setWindowTitle('TreeWidget 例子')
self.tree = QTreeWidget()
self.tree.setColumnCount(2) # 设置列数
# 设置头的标题
self.tree.setHeaderLabels(['Key','Value'])
root= QTreeWidgetItem(self.tree)
root.setText(0,'root')
root.setText(1,'0')
child1 = QTreeWidgetItem(root)
child1.setText(0,'child1')
child1.setText(1,'1')
child2 = QTreeWidgetItem(root)
child2.setText(0,'child2')
child2.setText(1,'2')
child3 = QTreeWidgetItem(root)
child3.setText(0,'child3')
child3.setText(1,'3')
child4 = QTreeWidgetItem(child3)
child4.setText(0,'child4')
child4.setText(1,'4')
child5 = QTreeWidgetItem(child3)
child5.setText(0,'child5')
child5.setText(1,'5')
self.tree.addTopLevelItem(root)
self.tree.clicked.connect( self.onTreeClicked ) # 点击时发射信号,连接槽函数onTreeClicked()
self.setCentralWidget(self.tree)
def onTreeClicked(self, qmodelindex):
item = self.tree.currentItem()
print("key=%s ,value=%s" % (item.text(0), item.text(1)))
if __name__ == '__main__':
app = QApplication(sys.argv)
tree = TreeWidgetDemo()
tree.show()
sys.exit(app.exec_())
案例--系统定制模式
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
if __name__ == '__main__':
app = QApplication(sys.argv)
# Window系统提供的模式
model = QDirModel()
# 创建一个QtreeView部件
tree = QTreeView()
# 为部件添加模式
tree.setModel(model)
tree.setWindowTitle( "QTreeView 例子" )
tree.resize(640, 480)
tree.show()
sys.exit(app.exec_())
容器
容器用于装载更多的控件,在现有的窗口空间中装载更多的控件。
QTabWidget
QTabWidget
控件提供了一个选项卡和一个页面区域,默认显示第一个选项卡的页面,通过单击各选项卡可以查看对应的页面。如果在一个窗口中显示的输入字段很多,可以对这些字段进行拆分,分别放置在不同页面的选项卡中。
QTabWidget
类中常用的方法:
方法 | 描述 |
---|---|
addTab() | 将一个控件添加到Tab 控件的选项卡中 |
insertTab() | 将一个Tab 控件的选项卡插入到指定的位置 |
removeTab() | 根据指定的索引删除Tab 控件 |
setCurrentIndex() | 设置当前可见的选项卡所在的索引 |
setCurrentWidget() | 设置当前可见的页面 |
setTabBar() | 设置选项卡栏的小控件 |
setTabPosition() | 设置选项卡的位置:QTabWidget.North :显示在页面上方;QTabWidget.South :显示在页面的下方;QTabWidget.West :显示在页面的左侧;QTabWidget.East :显示在页面的右侧 |
setTabText() | 定义Tab 选项卡的显示值 |
QTabWidget
类中常用的信号:
信号 | 描述 |
---|---|
currentChanged | 切换当前页面时发射该信号 |
案例--QTabWidget
的使用
一个表单的内容分为三组,每一组小控件都显示在不同的选项卡中,顶层窗口是一个QTabWidget
控件,将三个选项卡添加进去:
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class TabDemo(QTabWidget):
def __init__(self, parent=None):
super(TabDemo, self).__init__(parent)
# 设置三个选项卡,并添加进去
self.tab1 = QWidget()
self.tab2 = QWidget()
self.tab3 = QWidget()
self.addTab(self.tab1,"Tab 1")
self.addTab(self.tab2,"Tab 2")
self.addTab(self.tab3,"Tab 3")
self.tab1UI()
self.tab2UI()
self.tab3UI()
self.setWindowTitle("Tab 例子")
def tab1UI(self):
layout = QFormLayout()
layout.addRow("姓名",QLineEdit())
layout.addRow("地址",QLineEdit())
self.setTabText(0,"联系方式")
self.tab1.setLayout(layout)
def tab2UI(self):
layout = QFormLayout()
sex = QHBoxLayout()
sex.addWidget(QRadioButton("男"))
sex.addWidget(QRadioButton("女"))
layout.addRow(QLabel("性别"),sex)
layout.addRow("生日",QLineEdit())
self.setTabText(1,"个人详细信息")
self.tab2.setLayout(layout)
def tab3UI(self):
layout=QHBoxLayout()
layout.addWidget(QLabel("科目"))
layout.addWidget(QCheckBox("物理"))
layout.addWidget(QCheckBox("高数"))
self.setTabText(2,"教育程度")
self.tab3.setLayout(layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
demo = TabDemo()
demo.show()
sys.exit(app.exec_())
QStackedWidget
QStackedWidget
是一个堆栈窗口控件,可以填充一些小控件,但同时只有一个小控件可以显示,QStackedWidget
使用QStackedLayout
布局,可以有效的显示窗口中的控件。
案例--QStackedWidget
的使用
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class StackedExample(QWidget):
def __init__(self):
super(StackedExample, self).__init__()
self.setGeometry(300, 50, 10,10)
self.setWindowTitle('StackedWidget 例子')
self.leftlist = QListWidget ()
self.leftlist.insertItem (0, '联系方式' )
self.leftlist.insertItem (1, '个人信息' )
self.leftlist.insertItem (2, '教育程度' )
self.stack1= QWidget()
self.stack2= QWidget()
self.stack3= QWidget()
self.stack1UI()
self.stack2UI()
self.stack3UI()
self.Stack = QStackedWidget (self)
self.Stack.addWidget (self.stack1)
self.Stack.addWidget (self.stack2)
self.Stack.addWidget (self.stack3)
hbox = QHBoxLayout(self)
hbox.addWidget(self.leftlist)
hbox.addWidget(self.Stack)
self.setLayout(hbox)
# QListWidget的currentRoeChanged信号与槽函数相关联,改变堆叠控件的视图
self.leftlist.currentRowChanged.connect(self.display)
def stack1UI(self):
layout=QFormLayout()
layout.addRow("姓名",QLineEdit())
layout.addRow("地址",QLineEdit())
self.stack1.setLayout(layout)
def stack2UI(self):
layout=QFormLayout()
sex=QHBoxLayout()
sex.addWidget(QRadioButton("男"))
sex.addWidget(QRadioButton("女"))
layout.addRow(QLabel("性别"),sex)
layout.addRow("生日",QLineEdit())
self.stack2.setLayout(layout)
def stack3UI(self):
layout=QHBoxLayout()
layout.addWidget(QLabel("科目"))
layout.addWidget(QCheckBox("物理"))
layout.addWidget(QCheckBox("高数"))
self.stack3.setLayout(layout)
def display(self,i):
self.Stack.setCurrentIndex(i)
if __name__ == '__main__':
app = QApplication(sys.argv)
demo = StackedExample()
demo.show()
sys.exit(app.exec_())
QDockWidget
QDockWidget
是一个可以停靠在QMainWindow
内的窗口文件,它可以保持在浮动状态或者在指定位置作为子窗口附加到主窗口中。
QDockWidget
控件在主窗口内可以移动到新的区域。
QDockWidget
类中常用方法:
方法 | 描述 |
---|---|
setWidget() | 在Dock 窗口区域设置QWidget |
setFloating() | 设置Dock 窗口是否可以浮动,如果设置为True ,则表示可以浮动 |
setAllowedAreas() | 设置窗口可以停靠的区域:LeftDockWidgetArea :左边停靠区域;RightDockWidgetArea :右边停靠区域;TopDockWidgetArea :顶部停靠区域;BottomDockWidgetArea :底部停靠区域;NoDockWidgetArea :不显示Widget |
setFeatures() | 设置停靠窗口的功能属性:DockWidgetClosable :可关闭;DockWidgetMovable :可移动;DockWidgetFloatable :可漂浮;DockWidgetVerticalTitleBar :在左边显示垂直的标签栏;AllDockWidgetFeatures :具有前三种属性的所有功能;NoDockWidgetFeatures :无法关闭,不能移动,不能漂浮 |
案例--QDockWidget
的使用
顶层窗口是一个QMainWindow
对象,QTextEdit
对象是它的中央小控件:
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class DockDemo(QMainWindow):
def __init__(self, parent=None):
super(DockDemo, self).__init__(parent)
layout = QHBoxLayout()
bar=self.menuBar()
# 设置菜单栏
file=bar.addMenu("File")
file.addAction("New")
file.addAction("save")
file.addAction("quit")
# 创建停靠窗口items,在停靠窗口中添加QListWidget对象
self.items = QDockWidget("Dockable", self)
self.listWidget = QListWidget()
self.listWidget.addItem("item1")
self.listWidget.addItem("item2")
self.listWidget.addItem("item3")
self.items.setWidget(self.listWidget)
self.items.setFloating(False)
self.setCentralWidget(QTextEdit()) # QTextEdit对象是它的中央小控件
self.addDockWidget(Qt.RightDockWidgetArea, self.items) # 将停靠窗口放在中央小控件的右侧
self.setLayout(layout)
self.setWindowTitle("Dock 例子")
if __name__ == '__main__':
app = QApplication(sys.argv)
demo = DockDemo()
demo.show()
sys.exit(app.exec_())
QMdiArea
一个GUI
应用程序可能有多个窗口,选项卡和堆栈窗口控件允许一次使用其中一个窗口,但某个窗口在使用时,其他窗口的视图是隐藏的,所以我们可以用多文档界面来解决这个问题,其可以创建多个独立的窗口,这些窗口被称为SDI
(单文档界面),每个窗口都可以有自己的菜单系统、工具栏等。
MDI
(多文档界面)子窗口可以放在主窗口容器中,这个容器控件被称为QMdiArea
QMdiArea
控件通常占据QMainWindow
对象的中央位置,子窗口在这个区域是QMdiSubWindow
类的实例,可以设置任何QWidget
作为子窗口对象内部控件,子窗口在MDI
区域进行级联排列布局
QMdiArea
类和QMdiSubWindow
类中常用的方法:
方法 | 描述 |
---|---|
addSubWindow() | 将一个小控件添加在MDI 区域作为一个新的子窗口 |
removeSubWindow() | 删除一个子窗口中的小控件 |
setActiveSubWindow() | 激活一个子窗口 |
cascadeSubWindows() | 安排子窗口在MDI 区域级联显示 |
tileSubWindows() | 安排子窗口在MDI 区域平铺显示 |
closeActiveSubWindow() | 关闭活动的子窗口 |
subWindowList() | 返回MDI 区域的子窗口列表 |
setWidget() | 设置一个小控件作为QMsiSubwindow 实例对象的内部控件 |
案例--多文档界面的使用
主窗口QMainWindow
拥有一个菜单栏控件和MidArea
控件
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class MainWindow(QMainWindow):
count=0
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.mdi = QMdiArea()
self.setCentralWidget(self.mdi)
bar=self.menuBar()
file=bar.addMenu("File")
file.addAction("New")
file.addAction("cascade")
file.addAction("Tiled")
file.triggered[QAction].connect(self.windowaction) # 当菜单栏控件触发triggered信号时,连接到槽函数
self.setWindowTitle("MDI demo")
def windowaction(self, q):
print( "triggered")
if q.text()=="New": # 新建一个子窗口,并显示在主窗口中
MainWindow.count=MainWindow.count+1
sub=QMdiSubWindow()
sub.setWidget(QTextEdit())
sub.setWindowTitle("subwindow"+str(MainWindow.count))
self.mdi.addSubWindow(sub)
sub.show()
if q.text()=="cascade":
self.mdi.cascadeSubWindows() # 安排子窗口在MDI区域级联显示
if q.text()=="Tiled":
self.mdi.tileSubWindows() # 安排子窗口在MDI区域平铺显示
if __name__ == '__main__':
app = QApplication(sys.argv)
demo = MainWindow()
demo.show()
sys.exit(app.exec_())
程序运行结果:新建两个窗口后,安排子窗口在MDI
区域级联显示
QScrollBar
QScrollBar
使窗口控件提供水平的或垂直的滚动条,使得可以扩大当前窗口的有效装载面积,从而装载更多的控件
QScrollBar
类中常用的信号:
信号 | 含义 |
---|---|
valueChanged | 当滑动条的值改变时发射此信号 |
sliderMoved | 当用户拖动滑块时发射此信号 |
案例--QScrollBar
的使用
拖动滑动条的值来改变颜色:
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
hbox = QHBoxLayout( )
self.l1 = QLabel("拖动滑动条去改变颜色")
self.l1.setFont(QFont("Arial",16))
hbox.addWidget(self.l1)
self.s1 = QScrollBar()
self.s1.setMaximum(255)
self.s1.sliderMoved.connect(self.sliderval) # 当滑块滑动时,将sliderMoved信号和槽函数sliderval连接起来
self.s2 = QScrollBar()
self.s2.setMaximum(255)
self.s2.sliderMoved.connect(self.sliderval)
self.s3 = QScrollBar()
self.s3.setMaximum(255)
self.s3.sliderMoved.connect(self.sliderval)
hbox.addWidget(self.s1)
hbox.addWidget(self.s2)
hbox.addWidget(self.s3)
self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('QScrollBar 例子')
self.setLayout( hbox )
def sliderval(self):
print( self.s1.value(),self.s2.value(), self.s3.value() )
palette = QPalette()
c = QColor(self.s1.value(),self.s2.value(), self.s3.value(),255)
palette.setColor(QPalette.Foreground,c)
self.l1.setPalette(palette)
if __name__ == '__main__':
app = QApplication(sys.argv)
demo = Example()
demo.show()
sys.exit(app.exec_())
多线程
多线程技术涉及三种方法:使用计时器模块QTimer
,使用多线程模块QThread
和使用事件处理的功能。
QTimer
如果需要应用程序周期性地进行某项操作,就需要用到QTimer
实例,将其timeout
信号连接到相应的槽,调用start()
,之后定时器会以恒定的间隔发出timeout
信号。
使用时首先要引入QTimer
模块:from PyQt5.QtCore import QTimer
QTimer
类常用的方法:
方法 | 描述 |
---|---|
start(milliseconds) | 启动或重新启动定时器,时间间隔为毫秒,如果定时器已经运行,它将被停止并重新启动,如果singleShot 信号为真,定时器将仅被激活一次 |
Stop() | 停止定时器 |
QTimer
类中常用的信号:
信号 | 描述 |
---|---|
singleShot | 在给定的时间间隔后调用一个槽函数时发射此信号 |
timeout | 当定时器超时时发射此信号 |
self.timer = QTimer(self) # 初始化一个定时器
self.timer.timeout.connect(self.operate) # 计时结束调用operate()方法
self.timer.start(2000) # 设置计时器时间间隔并启动计时器
案例--QTimer
的使用
时间显示
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import QWidget, QPushButton , QApplication ,QListWidget, QGridLayout , QLabel
from PyQt5.QtCore import QTimer ,QDateTime
import sys
class WinForm(QWidget):
def __init__(self,parent=None):
super(WinForm,self).__init__(parent)
self.setWindowTitle("QTimer demo")
self.listFile= QListWidget()
self.label = QLabel('显示当前时间')
self.startBtn = QPushButton('开始')
self.endBtn = QPushButton('结束')
layout = QGridLayout(self)
self.timer = QTimer(self) # 初始化一个定时器
self.timer.timeout.connect(self.showTime) # 把定时器的timeout信号与槽函数showTime()连接
layout.addWidget(self.label,0,0,1,2)
layout.addWidget(self.startBtn,1,0)
layout.addWidget(self.endBtn,1,1)
self.startBtn.clicked.connect( self.startTimer)
self.endBtn.clicked.connect( self.endTimer)
self.setLayout(layout)
def showTime(self):
time = QDateTime.currentDateTime() # 获取系统现在的时间
timeDisplay = time.toString("yyyy-MM-dd hh:mm:ss dddd"); # 设置系统时间显示格式
self.label.setText( timeDisplay ) # 在标签上显示时间
def startTimer(self):
# 设置计时间隔并启动
self.timer.start(1000) # 时间间隔为1000ms,即1s
# 点击开始按钮后,计时器开始计时,禁用开始按钮,不禁用结束按钮
self.startBtn.setEnabled(False)
self.endBtn.setEnabled(True)
def endTimer(self):
self.timer.stop()
self.startBtn.setEnabled(True)
self.endBtn.setEnabled(False)
if __name__ == "__main__":
app = QApplication(sys.argv)
form = WinForm()
form.show()
sys.exit(app.exec_())
案例--弹出窗口,十秒钟消失,用于模仿程序启动界面
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
if __name__ == '__main__':
app = QApplication(sys.argv)
label = QLabel("<font color=red size=128><b>Hello PyQT,窗口会在10秒后消失!</b></font>")
label.setWindowFlags(Qt.SplashScreen|Qt.FramelessWindowHint) # 将弹出窗口设置为无边框
label.show()
QTimer.singleShot(10000, app.quit) # 设置10s后自动退出
sys.exit(app.exec_())
QThread
QThread
是Qt
线程类中最核心的底层类。
要使用QThread
开始一个线程,可以创建它的一个子类,然后覆盖其QThread.run()
函数。
# 创建一个自定义类,使其继承QThread,并实现run()方法
class Thread(QThread):
def __init__(self):
super(Thread,self).__init__()
def run(self):
#线程相关代码
pass
# 创建线程,使用线程时可以直接得到Thread实例,调用start()函数可以启动线程,线程启动后会自动调用其实现的run方法(线程的执行函数)
thread = Thread()
thread.start()
QThread
类中常用的方法和信号:
方法 | 描述 |
---|---|
start() | 启动线程 |
wait() | 阻止线程,直到满足如下条件之一:1.与此QThread 对象关联的线程已完成执行(即从run() 返回时),如果线程完成执行,此函数将返回True ,如果线程尚未启动,此函数也返回True ;2.等待时间的单位是毫秒,如果时间是ULONG_MAX (默认值),则等待,永远不会超时(线程必须从run() 返回):如果等待超时,此函数将返回False |
sleep() | 强制当前线程睡眠 |
QThread
类中常用的信号:
信号 | 描述 |
---|---|
started | 在开始执行run() 函数之前,从相关线程发射此信号 |
finished | 当程序完成业务逻辑时,从相关线程发射此信号 |
案例--QThread
的使用
在后台定时读取数据,并把返回的数据显示在界面中
# -*- coding: utf-8 -*-
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
class MainWidget(QWidget):
def __init__(self,parent=None):
super(MainWidget,self).__init__(parent)
self.setWindowTitle("QThread 例子")
self.thread = Worker()
self.listFile = QListWidget() # 创建一个多行文本框
self.btnStart = QPushButton('开始')
layout = QGridLayout(self)
layout.addWidget(self.listFile,0,0,1,2)
layout.addWidget(self.btnStart,1,1)
self.btnStart.clicked.connect( self.slotStart ) # 将按钮的clicked信号连接到slotStart()槽函数,单击按钮发射
self.thread.sinOut.connect(self.slotAdd) # 将线程的sinOut信号连接到slotAdd()槽函数
def slotAdd(self,file_inf): # slotAdd()函数负责在列表控件中动态添加字符串条目
self.listFile.addItem(file_inf)
def slotStart(self): # slotStart()槽函数
self.btnStart.setEnabled(False) # 将按钮设置为禁用状态
self.thread.start() # 开始线程
class Worker(QThread): # 定义一个线程类,当线程启动后,执行run()函数
sinOut = pyqtSignal(str)
def __init__(self,parent=None):
super(Worker,self).__init__(parent)
self.working = True
self.num = 0
def __del__(self):
self.working = False
self.wait()
def run(self):
while self.working == True:
file_str = 'File index {0}'.format(self.num)
self.num += 1
self.sinOut.emit(file_str) # 发出信号
self.sleep(2) # 线程休眠2秒
if __name__ == "__main__":
app = QApplication(sys.argv)
demo = MainWidget()
demo.show()
sys.exit(app.exec_())
网页交互
在PyQt5
中通过PyQt5.QtWebKitWidgets.QWebEngineView
类来使用网页控件
使用时先下载和导入相关的模块:
下载:pip install PyQt5 PyQtWebEngine
导入:from PyQt5.QtWebEngineWidgets import *
QWebEngineView
类中的常用方法:
方法 | 描述 |
---|---|
load(QUrl url) | 加载指定的URL 并显示 |
setHtml(QString &html) | 将网页视图的内容设置为指定的HTML 内容 |
QWebEngineView
控件使用load()
函数加载一个Web
页面,实际上是使用HTTP GET
方法加载Web
页面,这个控件既可以加载本地Web
页面,也可以加载远程的外部Web
页面
view = QWebEngineView()
view.load(QUrl('http://www.cnblogs.com/wangshuo1/')) view.show()
QWebEngineView
控件还可以使用setHtml()
函数加载本地的Web
代码
案例--加载并显示外部的Web
页面
# -*- coding: utf-8 -*-
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
import sys
class MainWindow(QMainWindow):
def __init__(self ):
super(QMainWindow, self).__init__()
self.setWindowTitle('打开外部网页例子')
self.setGeometry(5, 30, 1355, 730)
self.browser = QWebEngineView()
# 加载外部页面
self.browser.load(QUrl('http://www.cnblogs.com/wangshuo1')) # 输入一个外部的地址,进行加载访问
self.setCentralWidget(self.browser)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
案例--加载并显示本地的Web页面
# -*- coding: utf-8 -*-
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
import sys
class MainWindow(QMainWindow):
def __init__(self ):
super(QMainWindow, self).__init__()
self.setWindowTitle('加载并显示本地页面例子')
self.setGeometry(5, 30, 755, 530)
self.browser = QWebEngineView()
# 加载本地页面
url = r'D:/GithubProjects/PyQt5/Chapter05/web/index.html' # 本地Web的路径,注意用/分隔,不是属性中的\分隔
self.browser.load( QUrl( url ))
self.setCentralWidget(self.browser)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
案例--PyQt
调用JavaScript
代码
通过QWebEnginePage
类的runJavaScript(str, Callable)
函数可以方便的实现PyQt
和HTML/JavaScript
的双向通信,也实现了Python
代码和HTML/JavaScript
代码的解耦,便于开发人员进行分工协作。
PyQt
对象中访问JavaScript
的核心代码如下:
QWebEnginePag.runJavaScript(str, Callable)
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import QApplication , QWidget , QVBoxLayout , QPushButton
from PyQt5.QtWebEngineWidgets import QWebEngineView
import sys
# 创建一个 application实例
app = QApplication(sys.argv)
win = QWidget()
win.setWindowTitle('Web页面中的JavaScript与 QWebEngineView交互例子')
# 创建一个垂直布局器
layout = QVBoxLayout()
win.setLayout(layout)
# 创建一个 QWebEngineView 对象
view = QWebEngineView()
view.setHtml('''
<html>
<head>
<title>A Demo Page</title>
<script language="javascript">
// Completes the full-name control and
// shows the submit button
function completeAndReturnName() {
var fname = document.getElementById('fname').value;
var lname = document.getElementById('lname').value;
var full = fname + ' ' + lname;
document.getElementById('fullname').value = full;
document.getElementById('submit-btn').style.display = 'block';
return full;
}
</script>
</head>
<body>
<form>
<label for="fname">First name:</label>
<input type="text" name="fname" id="fname"></input>
<br />
<label for="lname">Last name:</label>
<input type="text" name="lname" id="lname"></input>
<br />
<label for="fullname">Full name:</label>
<input disabled type="text" name="fullname" id="fullname"></input>
<br />
<input style="display: none;" type="submit" id="submit-btn"></input>
</form>
</body>
</html>
''')
# 创建一个按钮去调用 JavaScript代码
button = QPushButton('设置全名')
def js_callback(result):
print(result)
def complete_name():
view.page().runJavaScript('completeAndReturnName();', js_callback)
# 按钮连接 'complete_name'槽,当点击按钮是会触发信号
button.clicked.connect(complete_name)
# 把QWebView和button加载到layout布局中
layout.addWidget(view)
layout.addWidget(button)
# 显示窗口和运行app
win.show()
sys.exit(app.exec_())
案例--JavaScript
调用PyQt
代码
JavaScript
调用PyQt
代码,是指PyQt
可以与加载的Web
页面进行双向的数据交互,首先,使用QWebEngineView
对象加载Web
页面后,就可以获得页面中表单输入数据,在Web
页面中通过JavaScript
代码用户提交的数据,然后在Web
界面中,JavaScript
通过桥连接方式传递数据给PyQt
。最后,PyQt
接收页面传递的数据,经过业务处理后,还可以把处理过的数据返回给Web
页面
创建QWebChannel
对象:
创建QWebChannel
对象,注册一个需要桥接的对象,以便Web
页面的JavaScript
使用,代码如下:
channel = QWebChannel()
myObj = MySharedObject()
channel.registerObject("bridge", myObj)
view.page().setWebChannel(channel)
创建共享数据的PyQt
对象:
创建的共享对象需要继承QWidget
对象或QObject
对象,其代码如下:
class MySharedObject(QWidget):
def __init__(self):
super(MyShareObject, self).__init__()
def _setStrValue(self, str):
print('获得页面参数:%s'% str)
# 需要定义对外发布的方法,需要使用pyqtProperty()函数让它暴露出来
strValue = pyqtProperty(str, fset=_setStrValue)