简介
Qt :跨平台UI工具,用于开源软件,可以用自由软件协议GPL
PyQt :是Qt为python提供的GUI扩展,实现了一个模块集,用python语言实现、封装了Qt所有的类,理论上讲Qt能开发的,PyQt也可以开发。PyQt5使用GPL自由软件协议。
GPL协议:软件版权属于开发者本人,软件产品受国际相关版权法保护。允许其他用户对原作者的软件进行复制或发行,并且可以在更改之后发行自己的的软件。但新软件在发布时也必须遵守GPL协议,不得对其进行附加限制。在GPL下不存在盗版一说,但用户不能将软件据为己有,比如申请软件产品专利等,因为这将违反GPL协议并且侵犯了原作者的版权。
开源许可的区别(转载)
PyQt5安装
#安装PyQt5, -i 使用豆瓣/阿里云提供的镜像
pip install PyQt5 -i https://pypi.douban.com/simple
pip install pillow -i https://mirrors.aliyun.com/pypi/simple/
也可以到https://pypi.douban.com/simple/pyqt5 直接下载需要版本的whl文件,离线安装
永久修改:在c:\users 当前用户创建目录pip,新建pip.ini
内容如下:(阿里云源)
[global]
index-url = http://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host = mirrors.aliyun.com
安装工具,如Qt Designer。不同的tools匹配的pyqt5版本有要求,不匹配时会下载匹配的版本,安装时卸载不匹配的版本
pip install PyQt5-tools -i https://pypi.douban.com/simple
一般tools安装在 python_path\lib\site-packages, 将路径 ..\pyqt5-tools添加到环境变量Path中
#### 安装后的测试
* 创建一个文件 qtui_test.py
```python
import sys
from PyQt5.QtWidgets import QApplication, QWidget,QPushButton
def show_w():
app = QApplication(sys.argv) # ([])
w = QWidget()
w.resize(500,300)
w.setWindowTitle('测试窗口')
btn = QPushButton('BUtton',w)
btn.resize(100,50),
btn.move(w.width() - 120,w.height() - 60)
w.show()
sys.exit(app.exec_())
if __name__ == '__main__':
show_w()
运行测试文件
python qtui_test.py
看到下面的窗口,恭喜,安装成功UI文件编译为py文件
pyuic5 -o destination.py source.ui
- 窗口放置到屏幕中间
class Winform(QMainWindows):
def __init__(self,parent=None):
super(WInform,self).__init__(parent) #关于supper(离自己最近的父类或平辈类,)
self.resize(300,400)
self.center()
def center(self):
screen = QDesktopWidget().screenGeometry()
size = self.geometry()
self.move((screen.width()-size.width())/2,(screen.height()-size.height())/2)
- 使用资源
创建资源文件
<RCC>
<qresource prefix="pic">
</qresource>
</RCC>
在Qt Designer中打开,添加相关资源。
编译成.py文件
pyrcc5 apprcc.qrc -o apprcc_rc.py
使用资源文件
#导入资源文件
import apprcc_rc
......
self.label.setText("")
self.label.setPixmap(QtGui.QPoxmap(":/pic/images/sample.jpg"))
- 窗口尺寸常用操作
#改变客户区大小
QWidget.resize(width,height)
QWidget.resize(QSize)
#获取客户区大小,位置
QWidget.size()
QWidget.width() / height()
.x() .y()
#设置客户区固定大小,不可更改
.setFixedWidth(int width) / .setFixedHeight(int height) #固定高或宽
.setFixedSize(int width , int height) # 固定高宽
#包含边框的
#获取窗口大小位置
QWidget.frameGeometry()
#设置窗口位置
QWidget.move(int x, int y)
QWidget.move(QPoint point)
- 创建主窗体
# -*- coding: UTF-8 -*-
import sys
from PyQt5.QtWidgets import QApplication ,QWidget
from PyQt5.QtGui import QIcon
#每个PyQt5程序需要一个QApplication对象,
app = QApplication(sys.argv)
window = QWidget()
window.resize(300,200)
window.move(250,150)
window.setWindowTitle('Hello')
window.setWindowIcon(QIcon('./images/wicon.icon')) #设置图标 路径为相对或绝对路径
window.show()
sys.exit(app.exec_()) # 进入程序主循环 运行成功返回0 否则非0
- QLabel
显示不可编辑的文本或图片或GIF,也可以作为伙伴buddy作为其他空间的提示标记,文本可以是纯文本、连接或富文本。
QObject - QPaintDevice - QWidget - QFrame - QLable
方法 | 描述 |
---|---|
setAlignment() | 对齐:Qt.AlignLeft, ..Right,Center,Justify(两端对齐),Top,Bottom,VCenter |
setIndent() | 文本缩进 |
setPixmap() | 设置QLabel为一个Pixmap图片 |
text() | 获得QLabel的文本内容 |
setText() | 设置QLabel内容 |
selectedText() | 返回已选择的字符 |
setBuudy() | 设置QLabel的助记符及buddy,即使用QLabel设置快捷键,按键后焦点落在其buddy上,buddy可以是任何一个Widget控件 |
setWordWrap() | 设置是否允许换行 |
常用信号
linkActivated : 单击超连接,setOpenExternalLinks = True
linkHovered: 鼠标滑过超链接。
label.setText("<a href='http://www.xxx.com'>欢迎访问xxx</a>")
label.linkHovered.connect( link_hovered )
label.linkActiveated.connect( link_clicked )
def link_hovered():
print("hovered")
- QLineEdit
输入单行文本类控件,输入多行用QTextEdit.
方法 | 描述 |
---|---|
setAlignment() | 与QLabel一样 |
clear() | 清空内容 |
setEchoMode() | 设置文本框显示格式 QLineEdit.Normal 正常显示;NoEcho 不显示任何内容;Password 显示密码掩码;PasswordEchoOnEdit 编辑时显示字符 |
setReadOnly() | 只读 |
setText(),Text() | 设置,获取文本 |
setValidator() | 校验输入,QintValidator 输入整数,QDoubleValidator 浮点,QRegexpValidator 符合正则表达式 |
其他 | setDragEnabled(),setMaxLength(),SelectAll(),setFocus(),setInputMask()设置掩码 |
常用信号
selectionChanged: 选择改变了
textChanged: 文本内容变化
editingFinished: 编辑结束
掩码
字符 | 含义 |
---|---|
A | ASCII字母是必须输入的(A-Z,a-z) |
a | ASCII字母允许输入,不是必须的 |
X | 任何字符都是必须的 |
x | 任何字符都是允许输入的,不是必须的 |
9 | 数字必须输入 |
0 | 数字允许输入,不是必须的 |
D | 1-9必须输入 |
d | 1-9允许输入,非必须 |
# | 数字或+ - 允许输入非必须 |
H | 十六进制必须输入 |
h | 十六进制允许输入 |
B,b | 二进制 |
> | 所有字母大写 |
< | 所有字母小写 |
! | 关闭大小写转换 |
示例:
000.000.000.000;_ IP地址,空白字符是_
HH:HH:HH:HH:HH:HH MAC地址
000-00-00 日期,空白字符是空格
AAAA-AAAA-AAA;# 空白字符是#,所有字母大写
pIntValidator = QintValidator(self)
pIntValidator.setRange(1,99)
pDoubleValidator = QDoubleValidator(self)
pDoubleValidator.setRange(-360,360)
pDoubleValidator.setNotation(
QDoubleValidator.StandardNotation)
pDoubleValidator.setDecimals(2)
reg = QRegExp("[a-zA-Z0-9]+$")
pValidator = QRegExpValidator(self)
pValidator.setRegExp(reg)
pIntLineEdit.setValidator(pIntValidator)
...
- QTextEdit
多行文本框,可显示文本或HTML文档
方法 | 描述 |
---|---|
setPlainText() | 设置内容 |
toPlainText() | 返回文本内容 |
setHtml() | 设置内容为Html |
toHtml() | 返回多行文本的html内容 |
clear() | 清空 |
QAbstrctButton
按钮类的基类,抽象类。
状态标记:isDown(),isChecked(),isEnable(),isCheckAble(),setAutoRepeat()长按时是否重复执行。
信号:
Pressed, Released, Clicked, Toggled 标记状态变化`QPushButton
方法 | 描述 |
---|---|
setCheckable() | 设置按钮是否已被选中,如果设置为True,标识按钮将保持已点击或释放状态 |
toggle() | 在按钮状态间切换 |
setIcon() | 设置图标 |
setEnabled() | 按钮是否可用 |
isChecked() | 返回按钮状态True False |
setDefault() | 设置按钮默认状态 |
setText() | 设置按钮显示文本 |
text() | 返回按钮显示文本 |
QRadioButton
单选按钮,多个按钮放入一个QGroupBox或QButtonGroup中,一次只能选一个。
主要方法:setCheckable(), isChecked(), setText(), text()
toggled信号在切换按钮状态时发射,clicked信号在每次点击否会发射,实际使用中,用toggled信号监控状态。QcheckBox
多选框,在状态变化时会发射一个stateChanged信号,isChecked查询是否被选中。还有第三种状态,“半选中”,标识状态没有变化,用setTristate()使他生效,使用checkState()来查询当前的切换状态。
主要方法:setChecked(), setText(), text() , isChecked(), setTriState()
三种状态:Qt.Checked 2,选中默认, Qt.PartiallyChecked 1 半选中 Qt.Unchecked 0 未选中QcomboBox
下拉列表框。
方法 | 描述 |
---|---|
addItem() | 添加一个下拉项 |
addItems() | 从列表添加下拉选项 |
Clear() | 删除所有选项 |
count() | 选项数目 |
currentText() | 返回选中文本 |
itemText(i) | 索引为i的文本 |
currenIndex() | 选中项索引 |
setItemText(int index,text) | 设置序号为index项的文本 |
信号
Activated : 选中一个下拉选项时
currentIndexChanged: 下拉索引发生改变
highlighted: 选中一个已选中的下拉选项
- QDialog
包括QMessageBox,QFileDialog、QFontDialog、QInputDialog等
方法:
setWindowTitle(),
setWindowModality() Qt.NonModal 非模态可与其他窗口交互 WindowModal 窗口模态 阻止与父窗口交互 ApplicationModal 应用程序模态,阻止和任何其他窗口交互
- QMessageBox
方法 | 描述 |
---|---|
information(QWidget parent,title,text,buttons,defaultButton) | 弹出消息对话框。parent 父窗口控件,title 标题 text 消息文本 buttons 多个标准按钮,默认Ok按钮,defaultButton,默认选中按钮 |
question(parent,title,text,buttons,defaultButton) | 同上 |
warming(parent,title,text,buttons,defaultButton) | 同上 |
about(parent ,title,text) | 同上 |
setTitle() | 设置标题 |
setText() | 设置消息正文 |
setIcon() | 弹出对话框的图片 |
标准按钮类型
按钮 | 描述 |
---|---|
QMessage.OK | OK |
QMessage.Cancel | Cancel |
QMessage.Yes | |
QMessage.No | |
QMessage.Abort | |
QMessage.Retry | |
QMessage.Ignore |
使用示例
reply = QMessageBox.information(self,'Title','Text',QmessageBox.Yes|QMessageBox.No,QMessageBox.Yes)
- QInputDialog
由文本框和OK Cancle组成,可输入数字,字符串,或列表选项。
方法 | 描述 |
---|---|
getInt() | 从控件中输入整数 |
getDouble() | 浮点 |
getText() | 字符串 |
getItem() | 列表选项 |
使用示例
items = ('a','b','c','d','e')
text,ok=QInputDialog.getItem(self,'selct item','列表值',items,0,False)
if ok and item:
self.lineedit.setText(item)
- QFontDialog
font, ok = QFontDialog.getFont()
if ok:
self.fontLineEdit.setFont(font)
- QFileDialog
方法 | 描述 |
---|---|
getOpenFileName() | 返回用户选择的文件名,打开文件 |
getSaveFileName() | 使用用户选择文件名,保存文件 |
setFileMode() | QFileDialog.AnyFile,任意文件;ExistingFile已存在的文件;Directory 文件目录;ExistingFiles 已存在的多个文件 |
setFilter() | 过滤器,显示允许的文件类型 |
fname, _ = QFileDialog.getOpenFileName(self,'OpenFile','C:\\',"Image files(*.jpg *.gif)")
self.label.setPixmap(QPixmap(fname))
def getfiles(self):
dlg = QFileDialog()
dlg.setFileMode(QFileDialog.AnyFile)
dlg.setFilter(QDir.Files)
if dlg.exec_():
filenames = dlg.selectedFiles()
f = open(filenames[0],'r')
with f:
data = f.read()
self.contents.setText(data)
- 窗口绘图类控件
主要包括QPainter、QPen、QBrush
- QPainter
在QWidget上执行绘图操作,是一个绘图工具,为大部分图形界面提供了高度优化的函数。
绘制操作在QWidget.paintEvent()中完成。绘制方法必须放在QtGui.QPainter对象的begin()和end()之间。
方法 | 描述 |
---|---|
begin() | 开始在目标设备上绘图 |
drawArc() | 在其实角度和最终角度之间画圆弧 |
drawEllipse() | 在一个矩形区域内画一个椭圆 |
drawLine(x,y,x,y) | 绘制直线,并设置当前画笔位置在后一个点 |
drawPixmap() | 从图形文件中提取pixmpa并显示在指定位置 |
drawPolygon() | 使用坐标数组绘制多边形 |
drawRect(x,y,w,h) | x,y画一个w,h的矩形 |
drawText() | 显示给定坐标处的文字 |
fillRect() | 使用QColor参数填充矩形 |
setBrush() | 设置画笔风格 |
setPen() | 画笔的颜色、大小和样式 |
画笔风格PenStyle
类型 | 描述 |
---|---|
Qt.NoPen | 无线条,如QPainter.drawRect()填充,但没有边界 |
.SolidLine | 单线条 |
.Dahsline | 虚线 |
.DotLine | 点划线 |
.DashDotLine | 虚点划线 |
.DashDotDotLine | |
.MpenStyle | 画笔风格的掩码 |
class Drawing(QWidget):
def __init__(self,parent=None):
super(Drawing,slef).__init__(parent)
self.setWindowTitle('Drawing')
self.resize(300,200)
self.text = '输出文字'
# 所有绘制方法都在绘制事件中发生,必须在begin和end之间
def paintEvent(slef,event):
painter = QPainter(self)
painter.begin(self)
self.drawText(event,painter)
painter.end()
# 输出文字
def drawText(self,event,qp):
qp.setPen(QColor(168,36,22)) # Qt.red
qp.drawText(event.rect(),Qt.AlignCenter,self.text)
#用点绘制正弦曲线
def drawPonts(self,qp):
qp.setPen(Qt.red)
for i in range(1000):
x = 100 * (-1+2.0*i/1000)
y = -50*math,sin((x-size.width()/2.0)*math.pi/50)
qp.drawPont(x,y)
if __name__ == "__main__":
app = QApplication(sys.argv)
dr = Drawing()
dr.show()
sys.exit(app.exec_())
- QPen
基本图形对象,用于绘制直线,曲线或矩形,椭圆,多边形及其他形状
pen = QPen(Qt.black, 2, Qt.SolidLine)
pen.setStyle(Qt.CustomDashLine)
pen.setDashPattern([1,4,5,4])
qp.setPen(pen)
qp.drawLine(....)
- QBrush
基本图形对象,用于填充如矩形,椭圆或多边形。QBrush有三种类型:预定义、过渡和纹理图案。
brush = QBrush(Qt.SolidPattern)
qp.setBrush(brush)
qp.drawRect(....)
- QPixmap
绘制图形,可以作为一个QPaintDevice对象,也可以加载到一个控件中,通常是标签或按钮。可读取类型BMP GIF JPG JPEG PNG PBM PGM PPM XBM XPM等
方法 | 描述 |
---|---|
copy() | 从QRect对象复制到QPixmap对象 |
fromImage() | 将QImage对象转为QPixmap对象 |
grabWidget() | 从给定的窗口小控件创建一个像素图 |
grabWindow() | 在窗口中创建数据的像素图 |
load() | 加载图像文件作为QPixmap对象 |
save() | 将QPixmap对象另存为文件 |
toImage() | 将QPixmap对象转为QImage对象 |
- QDrag
- QClipboard
- QCalendar
- QDateTimeEdit
- 菜单、工具栏和状态栏
- QStatusBar
self.statusBar = QStatusBar()
self.setStatusBar(self.statusBar)
方法|描述
|---|---|
addWidget()|在状态栏中添加给定的窗口小控件对象
addPermanentWidget()|在状态栏中永久添加给定的窗口小控件
showMessage()|在状态栏显示一条临时信息,显示指定时间时长
clearMessage()|删除临时显示的信息
removeWidget()|从状态栏中删除指定的小控件
20. QPrinter
打印图像,实际上是QPaintDevice中画图,与在QWidget、QPixmap和QImage中画图一样,创建一个QPainter对象进行画图,知识打印使用的是QPrinter。
21. 表格和树
* QTableView
一批数据进行交互,以表格输出,可以使用自定义的数据模型来显示内容,通过setModel来绑定数据。
QTableWidget继承自QTaleView,主要区别是QTableView可以使用自定义的数据模型来显示内容(先通过setModel来绑定数据源),而QTableWidget只能使用标准数据。且单元格数据是通过QTableWidgetItem对象来实现的。
QTableView可用模式如下
名称|说明
|---|---|
QStringListModel| 字符串
QStandardItemModel|任意层次结构的数据
QDirModel|文件系统进行封装
QSqlQueryModel|对SQL查询结果集进行封装
QSqlTableModel|对SQL表格进行封装
QSqlRelationTableModel|对带有foreign key的SQL表格进行封装
QSortFilterProxyModel|对模型中的数据进行排序或过滤
* QListView
*QTreeView
QWidget - QFrame - QAbstractScrollArea- QAbstractItemView - QTreeView - QTreeWidget
QTreeWidget常用方法
方法|描述
|---|---|
setColumnWidth(int column,int width)|将指定列的宽度设为给定值
insertTopLevelItems()|在试图的顶层索引中插入项目列表
expandAll()|展开所有节点
invisibleRootItem()|返回树形控件中不可见的根选项
selectedItems()|返回所有选定的非隐藏项目的列表
QTreeWidgetItem常用方法
方法|描述
|---|---|
addChild()|将子项追加到子列表中
setText()|设置显示的节点文本
Text()|返回显示的节点文本
setCheckState(column,state)|设置指定列的选中状态 Qt.Checked, UnChecked
setIcon(column,icon)|在制定的列表中显示图标
```python
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(1,160)
#设置子节点1
child1 = QTreeWidgetItem(root)
child1.setText(0,'child1')
child1.setText(1,'chiild1 col2')
child1.setIcon(0,QIcon("./images/xx.png"))
......其他节点
self.tree.addTopLevelItem(root)
self.tree.expandAll()
#也可以用以下方法添加
root = QTreeWidgetItem()
root.setText(0,'root')
rootList = []
rootList.append(root)
child1 = QTreeWidgetItem()
child1.setText(0,'child1')
child1.setText(1,'xxx')
root.addChild(child1)
self.tree.insertTopLevelItems(0,rootList)
# 设置节点状态
child1.setCheckState(0,Qt.Checked)
self.tree.clicked.connect(self.onTreeClicked)
def onTreeClicked(self,qmodeindex):
item = self.tree.currentItem()
print("key=%s,value=%s" %(item.text(0), item.text(1)))
系统定制模式
model = QDirModel()
tree = QTreeView()
tree.setModel(model)
tree.resize(300,400)
tree.show()
- 容器
- QTabWidget
- QStackWidget
- QDockWidget
- 多线程
- 事件处理
processEvents()在一些卡顿耗时的循环中使用QApplication.processEvents(),刷新页面。
*网页交互
QWebEngineView 加载显示外部web页面
调用JavaScript代码。QWebEnginePage.runJavaScript(str,Callable)
JavaScript调用pyqt代码
- 布局管理
#布局计算器的例子
grid = QGridLayout()
self.setLayout(grid)
names = ['Cls','Back','','Close',
'7','8','9','/',
'4','5','6','*',
'1','2','3','-',
'0','.','=','+']
positions = [(i,j) for i in range(5) for j in range(4)]
for postion,name in zip(positions,names):
if name == '' :
continue
button = QpushButton(name)
grid.addWidget(button, *position)
- 信号signal和槽slot
signal和slot是Qt中的核心机制,也是PyQt对象之间通讯的机制。每一个QObject对象和PyQt中继承制自QWidget的控件(这些都是QObject的子对象)都支持信号和槽。通过object.signal.connect()连接。
- 一个信号可以连接多个槽
- 一个信号可以连接另一个信号
- 信号参数可以是任何Python类型
- 一个槽可以监听多个信号
- 信号与槽的连接可以是同步,也可以是异步
- 信号与槽的连接可以跨线程
- 信号与槽可以断开
为QObject对象创建信号:
使用pyqtSignal()函数创建一个或多个重载的未经绑定的信号作为类的属性,信号只能在QObject的子类中定义。
信号必须在类创建时定义,不能在类创建后作为类的属性动态添加进来。
使用pyqtSignal()函数创建信号时,信号可以传递多个参数,并制定信号传递参数的类型,可以是 字符串,日期,bool,数字,列表,元组,字典。
定义:
class xx(QObject):
valueChanged = pyqtsignal([dict],[lisst])
- 使用内置信号与槽的使用
- 自定义信号与槽
不适用控件函数,使用自定义的函数。可以自定义传递参数。
from PyQt5.QtCore import QObject,pyqtSignal
class QTypeSingal(QObject)
#定义信号
sendmsg = pyqtSignal(object)
def __init__(self):
super(QTypeSignal,self).__init__()
def run(self):
self.sendmsg.emit('hello pyqt5')
#定义槽
class QTypeSlot(QObject):
def __init__(self):
super(QTypeSlot,self).__init__()
def get(self,msg):
print(msg)
if __name__ == '__main__':
send = QTypeSinal()
slot = QTypeSlot()
send.sendmsg.connect(slot.get)
send.run() #运行发射信号
装饰器信号与槽
通过装饰器的方法定义信号和槽函数。具体使用方法如下:
@PyQt5.QtCore.pyqtSlot(参数)
def on_发送对象名称_发射信号名称(self, 参数):
.....
self.okButton.setObjectName("okButton")
QtCore.QMetaObject.connectSlotsByName(self)
@QtCore.pyqtSlot()
def on_okButton_clicked(self):
print(' 单击了OK‘)