赞
踩
目录
参见CSDN:pyQt5环境的搭建_Hi~晴天大圣的博客-CSDN博客_pyqt5环境搭建
问题:在安装第三方库时出现报错"These Packages Do Not Match The Hashes From The Requirements File."
python在虚拟解释器环境中使用pip安装第三方库出现Requirement already satisfied错误
方法一: python -m PyQt5.uic.pyuic demo.ui -o demo.py
python文件夹//打开pyuic5程序 -o 文件名称 直接生成demo.py
课时18 调用源文件:RunDemo.py调用demo.py文件
QMainWindow:可以包含菜单栏,工具栏,状态栏和标题栏
QDialog:是对话窗口的基类。没有菜单栏,工具栏,状态栏
课时90 用Web浏览器控件(QWebEngineView)显示网页
课时94 JavaScript调用PyhtonAPI计算阶乘
课时127 实现不规则窗口(异形窗口)注意只对windowse系统有效果
课时136 使用可视化的方式对SQLite数据库进行增删改查操作
pyqt是一个用于创建GUI应用程序的跨平台工具包,它将python与qt库融为一体。也就是说,pyqt允许使用python语言调用qt库中的API。这样做的最大好处就是在保存了qt高运行效率的同时,大大提高开发效率。因为,使用python语言开发程序要比使用c++语言开发程序快的多。pyqt对qt做了完整的封装,几乎可以用pyqt做qt能做的任何事情。
由于目前最新的pyqt版本是5.11,所以习惯上称呼为pyqt为pyqt5
桌面应用,也可以成为GUI应用,在windows处于非常火爆的15年时间(1995到2010)里是非常火的,不过最近几年web应用和移动应用抢了风头。尽管web和移动应用看似成为现在的主流。但桌面应用目前仍然为很多类型应用的首选。移动应用由于屏幕太小,机器性能远低于同时代的pc机,所以至少目前来看,在短时间内移动应用是无法取代pc应用的,而在pc浏览器上运行的web应用的主要优势是不需要安装的,只要有浏览器就可以运行。
但缺点也显而易见,web应用在浏览器部分的逻辑代码通常都是由于javascript语言编写的,运行效率比较低,而且web应用是无法完全控制本机的硬件的,如摄像头,蓝牙设备,打印机,串口等,web应用在用户体验上也不如同时代的桌面应用,而web设备不擅长的事正好是桌面应用的强项,因此,在未来的几十年,桌面应用仍然会占有非常重要的地位。
Qt Designer
pyQt5基本窗口控件(QMainWindow,Qwidget,Qlabel,QLineEdit,菜单,工具栏等)
pyQt5高级控件(QTableView,QListView,容器,多线程等)
pyQt5布局管理(QBoxLayout,QGridLayout,QFormLayout,嵌套布局等)
pyQt5信号与槽(事件处理,数据传递等)
pyQt5图形与特效(定制窗口风格,绘图,QSS与UI美化,不规则窗口,设置样式等)
pyQt5扩展应用(制作pyQt5安装程序,数据处理,第三方绘图库在pyQt5中的应用,UI自动化测试等)
参见CSDN:
1 Python
2 PyQt模块插件
PyQt5中插件的作用:
QtDesigner——通过Qt语言进行UI设计(支持拖拽式的UI设计)
PyUIC——主要用来将QtDesigner代码转化成Python代码
Pyrcc—— 将图片、数据文件资源打包成py文件3 PyCharm
开发环境前期准备工作搭建完成!
课程讲解开始
课时(1-15) 开发第一个基于PyQt5的桌面应用
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/22 17:59
-
- import sys
-
- from PyQt5.QtWidgets import QApplication,QWidget
-
- '''
- 鉴于这两种情况中__name__的值是不同的:当一个模块被直接执行时,其__name__必然等于__main__;当一个模块被引用时,
- 其__name__必然等于文件名(不含.py)。所以利用判断__name__ == '__main__'的真假就可以将这两种情况区分出来。
- '''
- if __name__ == '__main__':
- #创建QApplication类的实例
- app=QApplication(sys.argv)
- #创建一个窗口
- w = QWidget()
- #设置窗口的尺寸
- w.resize(300,150)
- #移动窗口
- w.move(300,300)
- #设置窗口的标题
- w.setWindowTitle('第一个基于pyqt的桌面程序')
- #显示窗口
- w.show()
- #进入程序的主循环 并通过exit函数确保主循环安全结束
- sys.exit(app.exec_())
-
或者
ctrl+R预览
生成完成 !demo.py
python文件夹//打开pyuic5程序 -o 文件名称 直接生成demo.py
生成完成 !demo1.py
全选控件 右键 选择布局 为水平布局
其他布局设置方式同理 因为第二扩展菜单截图 截不到 这里请参考
CTRL + R 预览
新版本的QtDesigner里是没有WebView的,想要使用浏览器控件就需要自己安装QtWebEngine。安装之后也是没有图形界面的控件的,所以使用策略就是
用其他控件在图形界面布局,然后生成python代码之后在代码中修改
修改代码参考如下
from PyQt5 import QtWebEngineWidgets
self.webView = QtWebEngineWidgets.QWebEngineView(self.centralwidget)
self.webView.setGeometry(QtCore.QRect(300, 300, 451, 241))
self.webView.setUrl(QtCore.QUrl("https://markwannafly.blog.csdn.net/"))
self.webView.setObjectName("webView")
信号(signal)
是Qt的核心机制,也是PyQt的核心机制
信号:是由对象或者控件发射出去的消息
按钮的单击事件
当单击按钮时,按钮就会向外部发送单击消息,这些发送出去的信号需要一些代码来拦截,这些代码就是插槽上一个函数或者方法
一个信号可以和多个槽绑定,一个槽可以拦截多个信号
有3种窗口
QMainWindow
QWidget
QDialog
QDialog:是对话窗口的基类。没有菜单栏,工具栏,状态栏
QWidget:不确定窗口的用途,就使用QWidget
这里分享一个在线icon制作的网站:Icon图标在线制作工具
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/22 23:14
- import sys
- from PyQt5.QtWidgets import QMainWindow,QApplication
- from PyQt5.QtGui import QIcon
- class FirstMainWin(QMainWindow):
- def __init__(self):
- super(FirstMainWin,self).__init__()
- #设置主窗口的标题
- self.setWindowTitle("第一个主窗口应用")
-
- #设置窗口的尺寸
- self.resize(400,300)
-
- self.status=self.statusBar()
- self.status.showMessage("只存在5秒的消息",5000)
-
- #只有本程序可以调用 防止其他程序调用本程序
- if __name__ == '__main__':
- app=QApplication(sys.argv)
-
- app.setWindowIcon(QIcon('./and.png'))
- main=FirstMainWin()
- main.show()
- # 程序的主循环
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 11:38
- # 龙文学python
- # @Time 2022/11/22 23:14
- import sys
- from PyQt5.QtWidgets import QDesktopWidget,QMainWindow,QApplication
- from PyQt5.QtGui import QIcon
- class CenterForm(QMainWindow):
- def __init__(self):
- super(CenterForm,self).__init__()
- #设置主窗口的标题
- self.setWindowTitle("让主窗口居中")
-
- #设置窗口的尺寸
- self.resize(400,300)
-
- def center(self):
- # 获取屏幕坐标系
- screen=QDesktopWidget.screenGeometry()
- #获取窗口坐标系
- size=self.geometry()
- newLeft=(screen.width()-size.width())/2
- newTop=(screen.height()-size.height())/2
- self.move(newLeft,newTop)
-
- #只有本程序可以调用 防止其他程序调用本程序
- if __name__ == '__main__':
- app=QApplication(sys.argv)
-
- app.setWindowIcon(QIcon('./and.png'))
- main=CenterForm()
- main.show()
- # 程序的主循环
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 12:11
- import sys
- from PyQt5.QtWidgets import QDesktopWidget,QHBoxLayout,QMainWindow,QApplication,QPushButton,QWidget
-
- def onClick_Button():
- print("第一种方式 窗口坐标系 包含标题栏")
- print("widget.x()=%d" % widget.x())
- print("widget.y()=%d" % widget.y())
- print("widget.width()=%d" % widget.width())
- print("widget.height()=%d" % widget.height())
-
- print("第二种方式 窗口坐标系 不包含标题栏 只有工作区")
- print("widget.geometry().x()=%d" % widget.geometry().x())
- print("widget.geometry().y()=%d" % widget.geometry().y())
- print("widget.geometry().width()=%d" % widget.geometry().width())
- print("widget.geometry().height()=%d" % widget.geometry().height())
-
- print("第三种方式 暂时未理解全面")
- print("widget.frameGeometry().x()=%d" % widget.frameGeometry().x())
- print("widget.frameGeometry().y()=%d" % widget.frameGeometry().y())
- print("widget.frameGeometry().width()=%d" % widget.frameGeometry().width())
- print("widget.frameGeometry().height()=%d" % widget.frameGeometry().height())
- app=QApplication(sys.argv)
-
- widget=QWidget()
- btn=QPushButton(widget)
- btn.setText('按钮')
-
- btn.clicked.connect(onClick_Button)
-
- btn.move(55,55)
-
- widget.resize(300,240)#设置工作区的尺寸
-
- widget.move(250,200)
-
- widget.setWindowTitle('屏幕坐标系')
-
- widget.show()
-
- sys.exit(app.exec_())
-
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 12:40
- '''
- 窗口的setWindowIcon方法用于设置窗口的图标,只在windows中可用
- QAplication中的setQindowIcon的方法用于设置主窗口的图标和应用程序图标,但调用了窗口的setWindowIcon方法
- QAplication中的setQindowIcon的方法就只能用于设置应用程序图标了
- '''
- import sys
- from PyQt5.QtWidgets import QDesktopWidget,QMainWindow,QApplication
- from PyQt5.QtGui import QIcon
- class IconFrom(QMainWindow):
- def __init__(self):
- super(IconFrom,self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setGeometry(300, 300, 250, 250)
- #设置主窗口的标题
- self.setWindowTitle("设置窗口图标")
-
- #设置窗口图标
- self.setWindowIcon(QIcon('./and.png'))
-
-
- #只有本程序可以调用 防止其他程序调用本程序
- if __name__ == '__main__':
- app=QApplication(sys.argv)
-
- #app.setWindowIcon(QIcon('./and.png'))
- main=IconFrom()
- main.show()
- # 程序的主循环
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 12:51
- #显示控件提示信息
- import sys
- from PyQt5.QtWidgets import QDesktopWidget,QHBoxLayout,QMainWindow,QApplication,QToolTip,QPushButton,QWidget
- from PyQt5.QtGui import QIcon
- from PyQt5.QtGui import QFont
-
- class TooltipForm(QMainWindow):
- def __init__(self):
- super().__init__()
- self.initUI()
- def initUI(self):
- QToolTip.setFont(QFont("SansSerif",12))
- self.setToolTip('今天是<b>星期五<b>')
- self.setGeometry(300,300,200,200)
- self.setWindowTitle('设置控件提示信息')
-
- # 添加Button
- self.button1 = QPushButton("我的按钮")
- self.button1.setToolTip('这是一个按钮ok')
- layout = QHBoxLayout()
- layout.addWidget(self.button1)
-
- mainFrame = QWidget()
- mainFrame.setLayout(layout)
-
- self.setCentralWidget(mainFrame)
-
- #按钮点击事件方法(自定义的槽)
- def onClick_Button(self):
- sender=self.sender()
- print(sender.text()+'按钮被按下')
- app=QApplication.instance()
- #退出应用程序
- app.quit()
-
-
- #只有本程序可以调用 防止其他程序调用本程序
- if __name__ == '__main__':
- app=QApplication(sys.argv)
-
- app.setWindowIcon(QIcon('./and.png'))
- main=TooltipForm()
- main.show()
- # 程序的主循环
- sys.exit(app.exec_())
QLabel控件
setAlignment():设置文本的对齐方式
setIndent():设置文本缩进
text():获取文本内容
selectedText():返回所选择的字符
setWordWrap():设置是否允许换行
QLabel常用的信号(事件):
1.当鼠标滑过QLabel控件时出发:linkHovered
2.当鼠标单击QLabel控件时触发:linkActivated
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 12:51
- import sys
- from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout # 垂直布局
- from PyQt5.QtGui import QPalette # 调色版
- from PyQt5.QtGui import QPixmap # 展示图片
- from PyQt5.QtCore import Qt # 有一些常量在这里面,eg:blue
-
-
- class QLabelDdemo(QWidget):
- def __init__(self):
- super(QLabelDdemo, self).__init__()
- self.initUI()
-
- def initUI(self):
- label1 = QLabel(self)
- label2 = QLabel(self)
- label3 = QLabel(self)
- label4 = QLabel(self)
-
- label1.setText('<font color=yellow>这是一个文本标签</font>')
- label1.setAutoFillBackground(True) # 自动填充背景
- palette = QPalette()
- # 设置背景色
- palette.setColor(QPalette.Window, Qt.blue)#设置背景色
- # 对label1设置调色版
- label1.setPalette(palette)
-
- # 跳转到一个网页或者触发一个点击事件
- label2.setText("<a href='#'>欢迎使用Python GUI程序</a>")
-
- # 文本居中
- label3.setAlignment(Qt.AlignCenter)
- # 提示信息
- label3.setToolTip('这是一个图片标签')
- label3.setPixmap(QPixmap('./and.png'))
-
- # 如果设为True,用浏览器打开网页,如果设为False,调用槽函数
- label4.setOpenExternalLinks(True)
- label4.setText("<a href='www.baidu.com'>打开百度</a>")
- # 右对齐
- label4.setAlignment(Qt.AlignRight)
- label4.setToolTip('这是一个超级链接')
-
- vbox = QVBoxLayout()
- vbox.addWidget(label1)
- vbox.addWidget(label2)
- vbox.addWidget(label3)
- vbox.addWidget(label4)
-
- # 绑定信号和槽
- # 滑过事件
- label2.linkHovered.connect(self.linkHovered)
- # 单击事件
- label4.linkActivated.connect(self.linkClicked)
-
- self.setLayout(vbox)
- self.setWindowTitle('QLabel控件演示')
- self.resize(400, 300)
- return
-
- def linkHovered(self):
- print('当鼠标滑过label2标签时,触发事件')
-
- def linkClicked(self):
- print('当鼠标单击label4标签时,触发事件')
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = QLabelDdemo()
- main.show()
- sys.exit(app.exec_())
伙伴关系
举例:栅格布局下给控件设置伙伴关系
addWidget函数:
mainLayout . addWidget(控件对象, rowIndex, columnIndex, row, column)
第一个参数是要添加的控件对象,第二个和第三个是位置索引(行,列),就像矩阵一样是从(0,0)开始的,第四,五参数是空间大小,第四个是占几行,第五个是占几列
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 14:12
- from PyQt5.QtWidgets import *
- import sys
-
- '''
- QLabel与伙伴控件
- 控件对象 #组件对象
- rowIndex,columnIndex #控件位置
- row,column #指定控件的尺寸
- mainLayout.addWidget(控件对象,rowIndex,columnIndex,row,column)
- '''
- class QLabelBuddy(QDialog):
- def __init__(self):
- super(QLabelBuddy, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('QLabel与伙伴关系')
- self.resize(400, 150)
- # &代表设置热键,其后第一个字母就是热键,不区分大小写,Alt+热键调用即可
- nameLabel = QLabel('&Name(N)', self) # designer下的label
- nameLineEdit = QLineEdit(self) # designer下的lineEdit,即文本输入框
- # 设置伙伴关系
- nameLabel.setBuddy(nameLineEdit)
-
- passwordLabel = QLabel('&Password(P)', self) # designer下的label
- passwordLineEdit = QLineEdit(self) # designer下的lineEdit,即文本输入框
- # 设置伙伴关系
- passwordLabel.setBuddy(passwordLineEdit)
-
- btnOK = QPushButton('&OK(O)')
- btnCancel = QPushButton('&Cancel(C)')
- # 栅格布局
- mainlayout = QGridLayout(self)
- mainlayout.addWidget(nameLabel, 0, 0) # 放在第一行第一列
- # 放在第一行第二列,占用空间大小为一行两列(占用大小一行两列意思就是编辑框宽是标签控件的两倍)
- mainlayout.addWidget(nameLineEdit, 0, 1, 1, 2)
- mainlayout.addWidget(passwordLabel, 1, 0) # 放在第二行第一列
- mainlayout.addWidget(passwordLineEdit, 1, 1, 1, 2) # 放在第二行第二列,占用空间大小为一行两列
-
- mainlayout.addWidget(btnOK, 2, 1) # 第三行第二列
- mainlayout.addWidget(btnCancel, 2, 2) # 第三行第三列
- return
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = QLabelBuddy()
- main.show()
- sys.exit(app.exec_())
- 高级功能:EchoMode(回显模式)
-
- 基本功能:输入单行文本
-
- 4种回显模式:
-
- 1.Normal
-
- 就是正常的文本框输入,我们输入一个,文本框上就有一个
-
- 2.NoEcho
-
- 比如Linux下输入密码,输了半天感觉屏幕上啥也没输,但其实输入了,只不过不显示到屏幕上而已
-
- 3.Password
-
- 就像QQ登录一样,回显但回显的是小黑圆圈,用于输入密码
-
- 4.PasswordEchoOnEdit
-
- 也是输入密码时,处于编辑时会回显,但离开编辑状态时(比如把鼠标移到别的编辑框时)则变成小黑圆圈
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 14:44
-
- '''
- 课时32 QLineEdit控件与回显模式(EchoMode)
- '''
- from PyQt5.QtWidgets import *
- import sys
-
-
- class QLineEditEchoMode(QDialog):
- def __init__(self):
- super(QLineEditEchoMode, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('文件输入框的回显模式')
- self.resize(400, 300)
- # 表单布局
- formLayout = QFormLayout()
- # 创建编辑框
- normalLineEdit = QLineEdit()
- noEchoLineEdit = QLineEdit()
- passwordLineEdit = QLineEdit()
- passwordEchoOnEditLineEdit = QLineEdit()
- # 放入表单布局中
- formLayout.addRow('Normal', normalLineEdit)
- formLayout.addRow('NoEcho', noEchoLineEdit)
- formLayout.addRow('Password', passwordLineEdit)
- formLayout.addRow('PasswordEchoOnEdit', passwordEchoOnEditLineEdit)
- # placeholdertext(没输入时文本框里默认显示的灰色字体)
- normalLineEdit.setPlaceholderText('Normal')
- noEchoLineEdit.setPlaceholderText('NoEcho')
- passwordLineEdit.setPlaceholderText('Password')
- passwordEchoOnEditLineEdit.setPlaceholderText('PasswordEchoOnEdit')
- # 设置文本框回显模式
- normalLineEdit.setEchoMode(QLineEdit.Normal)
- noEchoLineEdit.setEchoMode(QLineEdit.NoEcho)
- passwordLineEdit.setEchoMode(QLineEdit.Password)
- passwordEchoOnEditLineEdit.setEchoMode(QLineEdit.PasswordEchoOnEdit)
-
- self.setLayout(formLayout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = QLineEditEchoMode()
- main.show()
- sys.exit(app.exec_())
-
-
校验器
如限制只能输入整数、浮点数或满足一定条件的字符串
代码问题:
限制范围的函数setRange有bug 需要正则表达式解决bug 可能在苹果系统可以(应该也不行) win系统不行
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 15:04 课时33 限制QLineEdi t控件的输入
-
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtGui import QIntValidator, QDoubleValidator, QRegExpValidator # 最后一个是正则表达式校验器
- from PyQt5.QtCore import QRegExp # 正则表达式类
-
-
- class QLineEditValidator(QWidget):
- def __init__(self):
- super(QLineEditValidator, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('文龙学校验器')
- # 创建表单布局
- formLayout = QFormLayout()
-
- intLineEdit = QLineEdit()
- doubleLineEdit = QLineEdit()
- validatorLineEdit = QLineEdit()
-
- formLayout.addRow('整数类型', intLineEdit)
- formLayout.addRow('浮点类型', doubleLineEdit)
- formLayout.addRow('数字和字母', validatorLineEdit)
-
- intLineEdit.setPlaceholderText('整型[1,99]')
- doubleLineEdit.setPlaceholderText('浮点类型[-360,360]')
- validatorLineEdit.setPlaceholderText('数字和字母')
-
- # 整数校验器[1,99]
- intValidator = QIntValidator(self) # 因为此函数需要一个QWidget对象作为参数,所以把自己传进去了
- intValidator.setRange(1, 99) # 试了试可以输入0
- # 浮点校验器[-1,360],精度:小数点后2位
- doubleValidator = QDoubleValidator(self) # 传self原因同上
- doubleValidator.setRange(-1, 360) # setRange有bug 需要正则表达式解决bug 可以在苹果系统可以(没有试过) win系统不行
- doubleValidator.setNotation(QDoubleValidator.StandardNotation)
- # 设置精度,小数点2位
- doubleValidator.setDecimals(2)
-
- # 字符和数字
- reg = QRegExp('[a-zA-Z0-9]+$') # 正则表达式
- validtor = QRegExpValidator(self) # 传self原因同上
- validtor.setRegExp(reg)
-
- # 设置校验器
- intLineEdit.setValidator(intValidator)
- doubleLineEdit.setValidator(doubleValidator)
- validatorLineEdit.setValidator(validtor)
-
- self.setLayout(formLayout)
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = QLineEditValidator()
- main.show()
- sys.exit(app.exec_())
-
用掩码限制QLineEdit控件的输入
- A:ASCII字母字符是必须输入的(A-Z、a-z)
- a:ASCII字母字符是允许输入的,但不是必需的(A-Z、a-z)
- N:ASCII字母字符是必须输入的(A-Z、a-z、0-9)
- n:ASCII字母字符是允许输入的,但不是必需的(A-Z. a-z、0-9)
- X:任何字符都是必须输入的
- x:任何字符都是允许输入的,但不是必需的
- 9:ASCII数字字符是必须输入的(0-9)
- 0:ASCII数字字符是允许输入的,但不是必需的(0-9)
- D:ASCII数字字符是必须输入的(1-9)
- d:ASCII数字字符是允许输入的,但不是必需的(1-9)
- #:ASCII数字字符或加减符号是允许输入的,但不是必需的
- H:十六进制格式字符是必须输入的(A-F、a-f、0-9)
- h:十六进制格式字符是允许输入的,但不是必需的(A-F、a-f、0-9)
- B:二进制格式字符是必须输入的(0, 1)
- b:二进制格式字符是允许输入的,但不是必需的(0, 1)
- >:所有的字母字符都大写
-
- <:所有字母字符都小写
-
- !:关闭大小写转换
-
- \:使用"\"转义上面列出的字符
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 15:26
- import sys
- from PyQt5.QtWidgets import *
-
-
- class QLineEditMask(QWidget):
- def __init__(self):
- super(QLineEditMask, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('用掩码限制QLineEdit控件的输入')
- formLayout = QFormLayout()
-
- ipLineEdit = QLineEdit() # ip地址
- macLineEdit = QLineEdit() # MAC地址
- dateLineEdit = QLineEdit() # 日期
- licenseLineEdit = QLineEdit() # 验证码
-
- #192.168.21.45
- # 最后加个分号和_意为没输入是默认显示_ ,前面的都是掩码,即ASCII数字字符是允许输入的,但不是必需的(0-9)
- ipLineEdit.setInputMask('000.000.000.000;_')
- macLineEdit.setInputMask('HH:HH:HH:HH:HH:HH;_')
- dateLineEdit.setInputMask('0000-00-00')
- licenseLineEdit.setInputMask('>AAAAA-AAAAA-AAAAA-AAAAA-AAAAA;#') # 若没有输入显示井号
-
- formLayout.addRow('数字掩码', ipLineEdit)
- formLayout.addRow('MAC掩码', macLineEdit)
- formLayout.addRow('日期掩码', dateLineEdit)
- formLayout.addRow('许可证掩码', licenseLineEdit)
-
- self.setLayout(formLayout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = QLineEditMask()
- main.show()
- sys.exit(app.exec_())
-
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 15:37
- from PyQt5.QtWidgets import *
- from PyQt5.QtGui import *
- from PyQt5.QtCore import Qt
- import sys
-
-
- class QLine_comprehensive_case(QWidget):
- def __init__(self):
- super(QLine_comprehensive_case, self).__init__()
- self.initUI()
-
- def initUI(self):
- '''
- 控件定义及属性设置
- '''
- edit1 = QLineEdit()
- # int校验器
- edit1.setValidator(QIntValidator())
- # 设置最大位数为4位,即不超过9999
- edit1.setMaxLength(4)
- # 右对齐
- edit1.setAlignment(Qt.AlignRight)
- # 这个字号直接影响输入框的尺寸
- edit1.setFont(QFont('Arial', 18))
-
- edit2 = QLineEdit()
- edit2.setValidator(QDoubleValidator(0.99, 99.99, 2)) # 2是精度,即小数点后几位
-
- edit3 = QLineEdit()
- edit3.setInputMask('99_9999_999999;#')
-
- edit4 = QLineEdit()
- edit4.textChanged.connect(self.textChanged) # 绑定信号和槽
-
- edit5 = QLineEdit()
- edit5.setEchoMode(QLineEdit.Password)
- edit5.editingFinished.connect(self.enterPress) # 绑定信号和槽
-
- edit6 = QLineEdit('Hello Pyqt5!')
- edit6.setReadOnly(True) # 只读
-
- '''
- 将控件添加到表单
- '''
- formlayout = QFormLayout()
- formlayout.addRow('整数校验', edit1)
- formlayout.addRow('浮点数校验', edit2)
- formlayout.addRow('input mask', edit3)
- formlayout.addRow('文本变化', edit4)
- formlayout.addRow('密码', edit5)
- formlayout.addRow('只读', edit6)
-
- '''
- 设置主窗口属性
- '''
- self.setLayout(formlayout)
- self.setWindowTitle('QLineEdit综合案例')
-
- '''
- 槽函数
- '''
-
- def textChanged(self, text):
- print('输入的内容' + text)
-
- def enterPress(self):
- print('已输入值')
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = QLine_comprehensive_case()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 16:30
- from PyQt5.QtWidgets import *
- import sys
-
-
- class QTextEditDemo(QWidget):
- def __init__(self):
- super(QTextEditDemo, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('QTextEdit控件演示')
- self.resize(300, 320)
-
- # 定义控件
- self.textEdit = QTextEdit()
- self.buttonText = QPushButton('显示文本')
- self.buttonHTML = QPushButton('显示HTML')
- self.buttonToText = QPushButton('获取文本')
- self.buttonToHTML = QPushButton('获取HTML')
-
- # 垂直布局
- layout = QVBoxLayout()
- layout.addWidget(self.textEdit)
- layout.addWidget(self.buttonText)
- layout.addWidget(self.buttonHTML)
- layout.addWidget(self.buttonToText)
- layout.addWidget(self.buttonToHTML)
-
- # 绑定信号和槽
- self.buttonText.clicked.connect(self.onClick_buttonText)
- self.buttonHTML.clicked.connect(self.onClick_buttonHTML)
- self.buttonToText.clicked.connect(self.onClick_buttonToText)
- self.buttonToHTML.clicked.connect(self.onClick_buttonToHTML)
-
- self.setLayout(layout)
-
- # 槽函数
- def onClick_buttonText(self):
- # 普通文本
- self.textEdit.setPlainText('Hello World!')
-
- def onClick_buttonHTML(self):
- # 富文本(HTML)
- self.textEdit.setHtml('<font color="blue" size="5">Hello World</font>')
-
- def onClick_buttonToText(self):
- print(self.textEdit.toPlainText()) # 控制台输出普通文本
-
- def onClick_buttonToHTML(self):
- print(self.textEdit.toHtml()) # 控制台输出HTML文本
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = QTextEditDemo()
- main.show()
- sys.exit(app.exec_())
- QAbstractButton(所有按钮控件的父类)
- QPushButton(普通按钮)
- AToolButton(工具条按钮)
- QRadioButton(单选框按钮)
- QCheckBox(复选框按钮)
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 16:47
-
- import sys
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
- from PyQt5.QtWidgets import *
-
-
- class QPushButtonDemo(QDialog):
- def __init__(self):
- super(QPushButtonDemo, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('QPushButton Demo')
- self.resize(350, 200)
-
- layout = QVBoxLayout() # 垂直布局
-
- self.btn1 = QPushButton('第一个按钮')
- self.btn1.setText('First Button1')
- # 下面两句配合使用,功能类似于单选框按钮QCheckBox
- self.btn1.setCheckable(True)
- self.btn1.toggle() # 按一下就按下去了,再按一下才能抬起
- # btn1一个信号对应两个槽函数
- self.btn1.clicked.connect(self.buttonState) # 先绑定谁系统就先调用谁
- self.btn1.clicked.connect(lambda: self.whichButton(self.btn1))
-
- layout.addWidget(self.btn1)
- # 在文本前面显示图像
- self.btn2 = QPushButton('图像按钮')
- self.btn2.setIcon(QIcon(QPixmap('./and.png')))
- self.btn2.clicked.connect(lambda: self.whichButton(self.btn2))
- layout.addWidget(self.btn2)
-
- self.btn3 = QPushButton('不可用的按钮')
- self.btn3.setEnabled(False)
- layout.addWidget(self.btn3)
-
- self.btn4 = QPushButton('&MyButton') # 设置了热键M/m
- self.btn4.setDefault(True) # 如果没有任何按钮被选中,那么按回车就是按了这个按钮
- self.btn4.clicked.connect(lambda: self.whichButton(self.btn4))
- layout.addWidget(self.btn4)
-
- self.setLayout(layout)
-
- '''
- 注意下面的方法是两个参数,如果用传统的信号与槽连接方式的话,只会将按钮对象本身传入,那样的话第二个参数就没有传入值了
- 所以要用lambda表达式,当前对象直接调用这个函数,传入的值就对应第二个参数了
- '''
-
- def whichButton(self, btn):
- # self.sender() #通过此方法可得到是哪个按钮被按下,或者可用此方法中的传参方法
- print('被单击的按钮是<' + btn.text() + '>')
-
- def buttonState(self):
- if self.btn1.isChecked():
- print('按钮1已经被选中')
- else:
- print('按钮1未被选中')
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = QPushButtonDemo()
- main.show()
- sys.exit(app.exec_())
在一个容器内的单选按钮是互斥的,即选中了一个单选按钮,就不能再选中另一个单选按钮,也就是不能同时处于选中状态。在不同容器中的单选按钮是分开的,互不影响。
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 17:12
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtGui import *
- from PyQt5.QtCore import *
-
-
- class QRatioButtonDemo(QWidget):
- def __init__(self):
- super(QRatioButtonDemo, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('QRatioButton')
- self.resize(350, 100)
- # 水平布局
- layout = QHBoxLayout()
-
- self.btn1 = QRadioButton('单选按钮1')
- # 设为默认是选中状态
- self.btn1.setChecked(True)
- # toggled是状态切换的信号
- self.btn1.toggled.connect(self.buttonState)
- layout.addWidget(self.btn1)
-
- self.btn2 = QRadioButton('单选按钮2')
- self.btn2.toggled.connect(self.buttonState)
- layout.addWidget(self.btn2)
-
- self.setLayout(layout)
-
- def buttonState(self):
- ratiobtn = self.sender()
- if ratiobtn.isChecked() == True:
- print('<' + ratiobtn.text() + '>被选中')
- else:
- print('<' + ratiobtn.text() + '>被取消选中状态')
- # 同一容器下单选按钮是互斥的,所以不必利用ratiobtn.text()来分情况判断
- '''
- if ratiobtn.text()=='单选按钮1':
- #是否被选中
- if ratiobtn.isChecked()==True:
- print('<'+ratiobtn.text()+'>被选中')
- else:
- print('<'+ratiobtn.text()+'>被取消选中状态')
- if ratiobtn.text()=='单选按钮2':
- if ratiobtn.isChecked()==True:
- print('<'+ratiobtn.text()+'>被选中')
- else:
- print('<'+ratiobtn.text()+'>被取消选中状态')
- '''
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = QRatioButtonDemo()
- main.show()
- sys.exit(app.exec_())
-
- 3种状态:
-
- 未选中:0
-
- 半选中:1
-
- 选中:2
-
- tristate属性表示复选框是三种状态还是两种状态,如果tristate为true,则表示复选框中有选中,半选中,未选中三种状态,即setTristate(True)即表示允许半选中。
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 17:39
-
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtGui import *
- from PyQt5.QtCore import *
- from PyQt5.QtCore import Qt # 其中有许多常量
-
-
- class QCheckBoxDemo(QWidget):
- def __init__(self):
- super(QCheckBoxDemo, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('QCheckBoxDemo')
- self.resize(350, 100)
- layout = QHBoxLayout()
-
- self.checkbox1 = QCheckBox('复选框控件1')
- # 默认选中
- self.checkbox1.setChecked(True) # 此函数只有两种状态
- self.checkbox1.stateChanged.connect(lambda: self.checkboxState(self.checkbox1))
- layout.addWidget(self.checkbox1)
-
- self.checkbox2 = QCheckBox('复选框控件2')
- self.checkbox2.stateChanged.connect(lambda: self.checkboxState(self.checkbox2))
- layout.addWidget(self.checkbox2)
-
- self.checkbox3 = QCheckBox('半选中控件3')
- # 设置选中有三个状态(即允许半选中)
- self.checkbox3.setTristate(True)
- # setCheckState函数有三种状态:Unchecked,PartiallyChecked,Checked
- self.checkbox3.setCheckState(Qt.PartiallyChecked)
- self.checkbox3.stateChanged.connect(lambda: self.checkboxState(self.checkbox3))
- layout.addWidget(self.checkbox3)
-
- self.setLayout(layout)
-
- def checkboxState(self, cb):
- check1Status = self.checkbox1.text() + ',isChecked=' + str(self.checkbox1.isChecked()) + ',isCheckstate=' + str(
- self.checkbox1.checkState()) + '\n'
- check2Status = self.checkbox2.text() + ',isChecked=' + str(self.checkbox2.isChecked()) + ',isCheckstate' + str(
- self.checkbox2.checkState()) + '\n'
- check3Status = self.checkbox3.text() + ',isChecked=' + str(self.checkbox3.isChecked()) + ',isCheckstate' + str(
- self.checkbox3.checkState()) + '\n'
- print(check1Status + check2Status + check3Status)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = QCheckBoxDemo()
- main.show()
- sys.exit(app.exec_())
1 如何将列表项添加到QComboBox控件中
2 如何获取选中的列表项
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 17:56
-
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtGui import *
- from PyQt5.QtCore import *
- from PyQt5.QtCore import Qt # 其中有许多常量
-
-
- class QComboBoxDemo(QWidget):
- def __init__(self):
- super(QComboBoxDemo, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('QComboBoxDemo')
- self.resize(350, 100)
- # 垂直布局
- layout = QVBoxLayout()
-
- self.label = QLabel('请选择编程语言')
- self.cb = QComboBox()
- self.cb.addItem('JavaEE')
- self.cb.addItem('Uniapp')
- self.cb.addItems(['Python', '大数据', '区块链'])
- # 每一项都对应一个下标索引
- self.cb.currentIndexChanged.connect(self.selectionChange) # 此信号默认传递两个参数(控件本身,索引)
-
- layout.addWidget(self.label)
- layout.addWidget(self.cb)
-
- self.setLayout(layout)
-
- def selectionChange(self, i):
- # 标签会随着当前选中的下拉项而改变
- self.label.setText(self.cb.currentText())
- self.label.adjustSize()
-
- for j in range(self.cb.count()):
- print('item' + str(j) + '=' + self.cb.itemText(j))
-
- print('current index', i, 'selection changed', self.cb.currentText())
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = QComboBoxDemo()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 18:20
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtGui import *
- from PyQt5.QtCore import Qt # 其中有许多常量
-
-
- class QSliderDemo(QWidget):
- def __init__(self):
- super(QSliderDemo, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('QSlider演示')
- self.resize(350, 500)
- # 垂直布局
- layout = QVBoxLayout()
-
- self.label = QLabel('Hello PyQt5!')
- self.label.setAlignment(Qt.AlignCenter)
- layout.addWidget(self.label)
-
- # 滑块分为水平和垂直两种
- # 水平slider1
- self.slider1 = QSlider(Qt.Horizontal) # 水平,左右滑动
- # 设置最小值
- self.slider1.setMinimum(12)
- # 设置最大值
- self.slider1.setMaximum(48)
- # 步长
- self.slider1.setSingleStep(3)
- # 设置当前值
- self.slider1.setValue(18)
- # 设置刻度的位置,刻度在下方
- self.slider1.setTickPosition(QSlider.TicksBelow)
- # 刻度间隔
- self.slider1.setTickInterval(6)
- self.slider1.valueChanged.connect(self.valueChange)
-
- # 垂直slider2
- self.slider2 = QSlider(Qt.Vertical) # 垂直滑块
- self.slider2.setMinimum(1)
- self.slider2.setMaximum(80)
- self.slider2.setSingleStep(5)
- self.slider2.setTickPosition(QSlider.TicksLeft) # 刻度条放在滑块的左边
- self.slider2.setTickInterval(10)
- self.slider2.valueChanged.connect(self.valueChange)
-
- layout.addWidget(self.slider1)
- layout.addWidget(self.slider2)
- self.setLayout(layout)
-
- def valueChange(self):
- '''
- 注意这里是sender(),而不是slider1也不是slider2,sender()获取当前操作的控件,
- 这样无论拖动哪个滑动条字体大小都会变化,因为这俩信号对应这一个槽函数
- '''
- print('当前值:%s' % self.sender().value())
- size = self.sender().value() # 获得当前值
- # 使字号根据当前值来变化
- self.label.setFont(QFont('Arial', size))
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = QSliderDemo()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 18:34
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtGui import *
- from PyQt5.QtCore import Qt # 其中有许多常量
-
-
- class QSpinBoxDemo(QWidget):
- def __init__(self):
- super(QSpinBoxDemo, self).__init__()
- self.initUI()
-
- def initUI(self):
- ####################################### 窗口设置
- self.setWindowTitle('QSliderDemo')
- self.resize(350, 120)
- # 垂直布局
- layout = QVBoxLayout()
- ######################################## 控件
- self.label = QLabel('当前值')
- self.label.setAlignment(Qt.AlignCenter)
-
- self.sb = QSpinBox()
- # 默认值
- self.sb.setValue(18)
- # 设置范围
- self.sb.setRange(10, 38)
- # 设置步长
- self.sb.setSingleStep(3)
- ####################################### 信号与槽
- self.sb.valueChanged.connect(self.valueChange)
-
- ####################################### 组装
- layout.addWidget(self.label)
- layout.addWidget(self.sb)
- self.setLayout(layout)
-
- def valueChange(self):
- self.label.setText('当前值:' + str(self.sb.value()))
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = QSpinBoxDemo()
- main.show()
- sys.exit(app.exec_())
QMessageBox 消息对话框
QColorDialog 颜色对话框
QFileDialog 文件对话框
QFontDia log 字体对话框
QInputDialog 输入对话框(获取输入信息)
主要用于显示软件的版本和作者及其他和软件息息相关的信息
常用的消息对话框:
1.关于对话框
2.错误对话框
3.警告对话框
4.提问对话框
5.消息对话框
有2点差异
1.显示的对话框图标可能不同
2.显示的按钮是不一样的
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 19:18
- import sys
- from PyQt5.QtWidgets import *
-
-
- class QMessageBoxDemo(QWidget):
- def __init__(self):
- super(QMessageBoxDemo, self).__init__()
- self.initUI()
-
- def initUI(self):
- # 窗口设置
- self.setWindowTitle('QMessageBoxDemo')
- self.resize(400, 300)
-
- # 控件
- self.btn1 = QPushButton()
- self.btn1.setText('显示关于对话框')
- self.btn2 = QPushButton()
- self.btn2.setText('显示消息对话框')
- self.btn3 = QPushButton()
- self.btn3.setText('显示警告对话框')
- self.btn4 = QPushButton()
- self.btn4.setText('显示错误对话框')
- self.btn5 = QPushButton()
- '''
- 一般是提问用户,让用户做出选择
- 比如关闭一个正在编辑的文件,如果没有保存,软件会提示你是否保存
- 或者要覆盖一个文件的话,会提示是否要覆盖等
- '''
- self.btn5.setText('显示提问对话框')
-
- # 信号与槽绑定
- self.btn1.clicked.connect(self.showDialog)
- self.btn2.clicked.connect(self.showDialog)
- self.btn3.clicked.connect(self.showDialog)
- self.btn4.clicked.connect(self.showDialog)
- self.btn5.clicked.connect(self.showDialog)
-
- # 布局
- layout = QVBoxLayout()
- layout.addWidget(self.btn1)
- layout.addWidget(self.btn2)
- layout.addWidget(self.btn3)
- layout.addWidget(self.btn4)
- layout.addWidget(self.btn5)
- self.setLayout(layout)
-
- # 槽函数
- def showDialog(self):
- text = self.sender().text()
- if text == '显示关于对话框':
- QMessageBox.about(self, '关于', '这是一个关于对话框')
- elif text == '显示消息对话框':
- '''
- 第二个参数是窗口名,第三个参数是窗口内容
- 最后一个参数是默认的,什么也不做,按回车就执行默认选项
- '''
- reply = QMessageBox.information(self, '消息', '这是一个消息对话框', QMessageBox.Yes | QMessageBox.No,
- QMessageBox.Yes)
- print(reply == QMessageBox.Yes)
- elif text == '显示警告对话框':
- QMessageBox.warning(self, '警告', '这是一个警告对话框', QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
- elif text == '显示错误对话框':
- QMessageBox.critical(self, '警告', '这是一个错误对话框', QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
- elif text == '显示提问对话框':
- QMessageBox.question(self, '提问', '这是一个提问对话框', QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = QMessageBoxDemo()
- main.show()
- sys.exit(app.exec_())
QInputDialog.getItem 用于显示输入列表,即往里传入一个元组或列表,就会显示一个QComboBox
QInputDialog.getText 用于录入普通文本
QInputDialog.getInt 用于输入整数的,显示一个计数器控件
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 19:38
- import sys
- from PyQt5.QtWidgets import *
-
-
- class QInputDialogDemo(QWidget):
- def __init__(self):
- super(QInputDialogDemo, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('QInputDialogDemo')
- self.resize(400, 150)
- # 表单布局
- layout = QFormLayout()
-
- self.btn1 = QPushButton('获取列表中的选项')
- self.btn1.clicked.connect(self.getItem)
- self.lineEdit1 = QLineEdit()
- layout.addRow(self.btn1, self.lineEdit1)
-
- self.btn2 = QPushButton('获取字符串')
- self.btn2.clicked.connect(self.getText)
- self.lineEdit2 = QLineEdit()
- layout.addRow(self.btn2, self.lineEdit2)
-
- self.btn3 = QPushButton('获取整数')
- self.btn3.clicked.connect(self.getInt)
- self.lineEdit3 = QLineEdit()
- layout.addRow(self.btn3, self.lineEdit3)
-
- self.setLayout(layout)
-
- # 槽函数
- # 下拉框
- def getItem(self):
- items = ('JavaEE', 'Uniapp', '大数据', '区块链', '人工智能')
- # 返回的是个元组,第一个元素就是input里对应的内容,第二个元素是个布尔量,如果对话框是按OK则返回1,取消就是返回0
- item, ok = QInputDialog.getItem(self, '请选择技术方向', '技术列表', items)
- print(ok) # 点了OK就返回True,点了Cancel就返回False
- if ok and item:
- self.lineEdit1.setText(item)
- print(ok)
-
- # 字符串
- def getText(self):
- text, ok = QInputDialog.getText(self, '文本输入框', '输入姓名')
- if ok and text:
- self.lineEdit2.setText(text)
-
- # 整数
- def getInt(self):
- num, ok = QInputDialog.getInt(self, '整数输入框', '输入数字')
- if ok and num:
- self.lineEdit3.setText(str(num))
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = QInputDialogDemo()
- main.show()
- sys.exit(app.exec_())
-
-
-
-
-
-
-
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 19:52
- import sys
- from PyQt5.QtWidgets import *
-
-
- class QFontDialogDemo(QWidget):
- def __init__(self):
- super(QFontDialogDemo, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('QFontDialogDemo')
- self.resize(400, 150)
- layout = QVBoxLayout()
-
- self.fontBtn = QPushButton('选择字体')
- self.fontBtn.clicked.connect(self.getFont)
- layout.addWidget(self.fontBtn)
-
- self.fontLabel = QLabel('Hello,测试字体例子')
- layout.addWidget(self.fontLabel)
-
- self.setLayout(layout)
-
- def getFont(self):
- (font, ok) = QFontDialog.getFont()
- if ok:
- self.fontLabel.setFont(font)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = QFontDialogDemo()
- main.show()
- sys.exit(app.exec_())
-
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 19:59
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtGui import QPalette
-
-
- class QColorDialogDemo(QWidget):
- def __init__(self):
- super(QColorDialogDemo, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('QColorDialogDemo')
- self.resize(400, 150)
- layout = QVBoxLayout()
-
- self.colorBtn = QPushButton('设置颜色')
- self.colorBtn.clicked.connect(self.getColor)
- layout.addWidget(self.colorBtn)
-
- self.colorBackBtn = QPushButton('设置背景颜色')
- self.colorBackBtn.clicked.connect(self.getBackColor)
- layout.addWidget(self.colorBackBtn)
-
- self.colorLabel = QLabel('Hello,测试颜色例子')
- layout.addWidget(self.colorLabel)
-
- self.setLayout(layout)
-
- def getColor(self):
- color = QColorDialog.getColor()
- # 调色板
- p = QPalette()
- # 注意WindowText(这是类属性,常量)的大小写,这是常量,别选错了!!!!
- p.setColor(QPalette.WindowText, color)
- print('QPalette.WindowText =', QPalette.WindowText)
- print('QPalette.Window =', QPalette.Window)
- self.colorLabel.setPalette(p)
-
- # 设置背景颜色
- def getBackColor(self):
- color = QColorDialog.getColor()
- p = QPalette()
- p.setColor(QPalette.Window, color)
- # 自动填充背景
- self.colorLabel.setAutoFillBackground(True)
- self.colorLabel.setPalette(p)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = QColorDialogDemo()
- main.show()
- sys.exit(app.exec_())
绘图API: 绘制文本
1.文本
2.各种图形(直线,点,椭圆,弧,扇形,多边形等)
3.图像QPainter过程:
painter = QPainter() #创建绘制对象
painter. begin() #开始绘制
painter. drawText(...) #绘制过程
painter. end() #结束绘制
必须在paintEvent事件方法(此方法窗口自动调用,创建窗口或窗口尺寸变化时)中绘制各种元素
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 20:29
- import sys
- from PyQt5.QtWidgets import QApplication, QWidget
- from PyQt5.QtGui import QPainter, QColor, QFont
- from PyQt5.QtCore import Qt
-
-
- class DrawText(QWidget):
- def __init__(self):
- super(DrawText, self).__init__()
- self.setWindowTitle('在窗口上绘制文本')
- self.resize(300, 200)
- self.text = 'CSDN王家视频教程图书馆'
-
- def paintEvent(self, event):
- painter = QPainter(self)
- painter.begin(self)
- print('窗口大小改变,此方法会不断调用')
- # 画笔
- painter.setPen(QColor(150, 43, 5)) # RGB
- # 字体,字号
- painter.setFont(QFont('SimSun', 25))
- # 绘图区域,居中,绘制文本
- painter.drawText(event.rect(), Qt.AlignCenter, self.text)
- painter.end()
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = DrawText()
- main.show()
- sys.exit(app.exec_())
- #核心代码参考
- for i in range(1000):
- x = 100 * (-1 + 2.0 * i / 1000) + size.width() / 2.0 # 加上size.width()/2.0是将绘制图像原点挪到窗口中间
- y = -50 * math.sin((x - size.width() / 2.0) * math.pi / 50) + size.height() / 2.0
- painter.drawPoint(x, y) # 说是曲线,其实是画了1000个点,看上去有点像曲线
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 20:34
- '''
- 用像素点绘制正弦曲线
- -2PI 2PI
- drawPoint(x,y)
- '''
-
- import sys, math
- from PyQt5.QtWidgets import *
- from PyQt5.QtGui import *
- from PyQt5.QtCore import Qt
-
-
- class DrawPoints(QWidget):
- def __init__(self):
- super(DrawPoints, self).__init__()
- self.resize(500, 300)
- self.setWindowTitle('在窗口上用像素点绘制2个周期的正弦曲线')
-
- def paintEvent(self, event):
- painter = QPainter() # 定义画图对象
- painter.begin(self) # 开始画图
- painter.setPen(Qt.blue)
- size = self.size()
-
- for i in range(1000):
- x = 100 * (-1 + 2.0 * i / 1000) + size.width() / 2.0 # 加上size.width()/2.0是将绘制图像原点挪到窗口中间
- y = -50 * math.sin((x - size.width() / 2.0) * math.pi / 50) + size.height() / 2.0
- painter.drawPoint(x, y) # 说是曲线,其实是画了1000个点,看上去有点像曲线
-
- painter.end() # 结束画图
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = DrawPoints()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 20:22
- import sys
- from PyQt5.QtWidgets import QApplication, QWidget
- from PyQt5.QtGui import QPainter, QColor, QFont, QPen
- from PyQt5.QtCore import Qt
-
-
- class DrawMutilLine(QWidget):
- def __init__(self):
- super(DrawMutilLine, self).__init__()
- self.setWindowTitle('设置Pen的样式')
- self.resize(350, 250)
-
- def paintEvent(self, event):
- painter = QPainter()
- painter.begin(self)
-
- # 颜色,粗细,画笔类型
- pen = QPen(Qt.red, 3, Qt.SolidLine) # 最后一个参数是实线
-
- painter.setPen(pen)
- painter.drawLine(20, 40, 250, 40)
-
- pen.setStyle(Qt.DashLine)
- painter.setPen(pen) # 切记设置完style之后,要再将pen设置一遍,否则不会起作用
- painter.drawLine(20, 80, 250, 80)
-
- pen.setStyle(Qt.DashDotDotLine)
- painter.setPen(pen)
- painter.drawLine(20, 120, 250, 120)
-
- pen.setStyle(Qt.DotLine)
- painter.setPen(pen)
- painter.drawLine(20, 160, 250, 160)
-
- pen.setStyle(Qt.CustomDashLine)
- pen.setDashPattern([1, 10, 5, 10]) # 线长度,间隔长度,线长度,间隔长度
- painter.setPen(pen)
- painter.drawLine(20, 200, 250, 200)
-
- painter.end()
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = DrawMutilLine()
- main.show()
- sys.exit(app.exec_())
绘制各种图形
弧
圆形
椭圆
矩形(正方形)
多边形
绘制图像
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 20:47
- import sys
- from PyQt5.QtWidgets import QApplication, QWidget
- from PyQt5.QtGui import QPainter, QPolygon, QImage
- from PyQt5.QtCore import Qt, QRect, QPoint
- import os
-
-
- class DrawAll(QWidget):
- def __init__(self):
- super(DrawAll, self).__init__()
- self.setWindowTitle('绘制各种图形')
- self.resize(400, 600)
-
- def paintEvent(self, event):
- qp = QPainter(self)
- qp.begin(self)
-
- qp.setPen(Qt.blue)
- # 绘制弧
- # 左上角坐标,宽,高
- rect = QRect(0, 10, 200, 200)
- # 绘制区域(在其中绘制,起始角度,结束角度)
- # alen:一个alen等于1/16度,eg:画45°的弧就是45*16
- qp.drawArc(rect, 0, 50 * 16)
- # 通过弧绘制圆
- qp.setPen(Qt.red)
- # rect也可直接当参数传进去
- qp.drawArc(120, 10, 100, 100, 0, 360 * 16)
- # 绘制带弦的弧
- rect1 = QRect(10, 120, 100, 100)
- qp.drawChord(rect1, 12, 130 * 16)
- # 绘制扇形
- rect2 = QRect(10, 240, 100, 100)
- qp.drawPie(rect2, 12, 130 * 16)
- # 椭圆(不需要指定角度)
- # 宽和高肯定是不一样的,如果一样就是圆了,所以绘制圆可以通过椭圆,也可以通过弧
- qp.drawEllipse(120, 120, 150, 100)
- # 绘制多边形
- # 五边形,需要五个点
- point1 = QPoint(140, 380)
- point2 = QPoint(270, 420)
- point3 = QPoint(290, 512)
- point4 = QPoint(290, 588)
- point5 = QPoint(200, 533)
- polygon = QPolygon([point1, point2, point3, point4, point5])
- qp.drawPolygon(polygon)
-
- # 绘制图像
- print(os.path.exists('./and.png')) # 此路径是否存在
- # 装载图像
- image = QImage('./and.png')
- # 将图像(面积)缩小64倍
- rect3 = QRect(10, 400, image.width() / 8, image.height() / 8)
- qp.drawImage(rect3, image)
-
- qp.end()
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = DrawAll()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 21:02
- import sys
- from PyQt5.QtWidgets import QApplication, QWidget
- from PyQt5.QtGui import QPainter, QPolygon, QImage, QBrush
- from PyQt5.QtCore import Qt, QRect, QPoint
-
-
- class FillRect(QWidget):
- def __init__(self):
- super(FillRect, self).__init__()
- self.setWindowTitle('绘制各种图形')
- self.resize(400, 200)
-
- def paintEvent(self, event):
- qp = QPainter(self)
- qp.begin(self)
-
- brush = QBrush(Qt.SolidPattern) # 实心
- qp.setBrush(brush)
- qp.drawRect(10, 15, 90, 60)
-
- brush = QBrush(Qt.Dense1Pattern)
- qp.setBrush(brush)
- qp.drawRect(130, 15, 90, 60)
-
- brush = QBrush(Qt.Dense2Pattern)
- qp.setBrush(brush)
- qp.drawRect(250, 15, 90, 60)
-
- brush = QBrush(Qt.Dense3Pattern)
- qp.setBrush(brush)
- qp.drawRect(10, 105, 90, 60)
-
- brush = QBrush(Qt.HorPattern)
- qp.setBrush(brush)
- qp.drawRect(130, 105, 90, 60)
-
- qp.end()
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = FillRect()
- main.show()
- sys.exit(app.exec_())
过程:
A.setDrapEnabled(True) 设置A支持拖拽
B. setAcceptDrops(True) 设置B可接收
B需要两个事件:
1. dragEnterEvent 将A拖到B触发
2. dropEvent 在B的区域放下A时触发
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 21:10
- import sys
- from PyQt5.QtWidgets import *
-
-
- # 下拉框类
- class MyComboBox(QComboBox):
- def __init__(self):
- super(MyComboBox, self).__init__()
- # 设置下拉框可接收
- self.setAcceptDrops(True)
-
- # 别的控件拖进来以后,还没松鼠标时,下面的函数触发
- def dragEnterEvent(self, e):
- print(e)
- # 是否是文本
- if e.mimeData().hasText():
- e.accept()
- else:
- e.ignore()
-
- # 当控件拖进来放下时,下面的函数触发
- def dropEvent(self, e):
- # 此时self代表当前下拉列表控件,
- self.addItem(e.mimeData().text())
-
-
- class DragDropDemo(QWidget):
- def __init__(self):
- super(DragDropDemo, self).__init__()
- formLayout = QFormLayout()
- formLayout.addRow(QLabel('请将左边的文本拖到右边的下拉列表中'))
- lineEdit = QLineEdit()
- # 让QLinEdit控件可拖动
- lineEdit.setDragEnabled(True)
- # 第一个类MyComboBox的实例
- combo = MyComboBox()
- formLayout.addRow(lineEdit, combo)
-
- self.setLayout(formLayout)
- self.setWindowTitle('拖拽案例')
- self.resize(400, 100)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = DragDropDemo()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 21:22
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtGui import *
- from PyQt5.QtCore import *
-
-
- class ClipBoardDemo(QDialog):
- def __init__(self):
- super(ClipBoardDemo, self).__init__()
- # 控件
-
- # 定义六个复制粘贴按钮,用来实现复制粘贴文本,图像和HTML网页
- textCopyBtn = QPushButton('复制文本')
- textPasteBtn = QPushButton('粘贴文本')
- htmlCopyBtn = QPushButton('复制HTML')
- htmlPasteBtn = QPushButton('粘贴HTML')
- imageCopyBtn = QPushButton('复制图像')
- imagePasteBtn = QPushButton('粘贴图像')
-
- # 多行文本
- self.textLabel = QLabel('默认文本')
-
- # 标签用于展示图片
- self.imageLabel = QLabel()
-
-
- # 定义网格栅格布局
- layout = QGridLayout()
- layout.addWidget(textCopyBtn, 0, 0)
- layout.addWidget(imageCopyBtn, 0, 1)
- layout.addWidget(htmlCopyBtn, 0, 2)
- layout.addWidget(textPasteBtn, 1, 0)
- layout.addWidget(imagePasteBtn, 1, 1)
- layout.addWidget(htmlPasteBtn, 1, 2)
- layout.addWidget(self.textLabel, 2, 0, 1, 2) # 坐标,行占的单位宽度,列占的单位宽度
- layout.addWidget(self.imageLabel, 2, 2)
-
- self.setLayout(layout)
-
- # 信号与槽
- textCopyBtn.clicked.connect(self.copyText)
- textPasteBtn.clicked.connect(self.pasteText)
- htmlCopyBtn.clicked.connect(self.copyHtml)
- htmlPasteBtn.clicked.connect(self.pasteHtml)
- imageCopyBtn.clicked.connect(self.copyImage)
- imagePasteBtn.clicked.connect(self.pasteImage)
-
- self.setWindowTitle('剪贴板演示')
-
- # 槽函数
- def copyText(self):
- # 剪贴板对象
- clipboard = QApplication.clipboard()
- clipboard.setText('hello csdn')
-
- def pasteText(self):
- clipboard = QApplication.clipboard()
- self.textLabel.setText(clipboard.text())
-
- def copyImage(self):
- clipboard = QApplication.clipboard()
- clipboard.setPixmap(QPixmap('./csdnlogo.jpg'))
-
- def pasteImage(self):
- clipboard = QApplication.clipboard()
- # clipboard.pixmap()是从剪贴板获得图像
- self.imageLabel.setPixmap(clipboard.pixmap())
-
- def copyHtml(self):
- mimeData = QMimeData() # 获得数据类型
- mimeData.setHtml('<b>Bold and <font color=red>Red</font></b>')
- clipboard = QApplication.clipboard()
- clipboard.setMimeData(mimeData)
-
- def pasteHtml(self):
- clipboard = QApplication.clipboard()
- mimeData = clipboard.mimeData() # 获得剪贴板数据
-
- # 如果剪贴板数据是html,这里普通文本也可以
- if mimeData.hasHtml():
- self.textLabel.setText(mimeData.html())
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = ClipBoardDemo()
- main.show()
- sys.exit(app.exec_())
-
日历控件:QCalendarWidget
控件:QDateTimeEdit
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 21:39
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtGui import *
- from PyQt5.QtCore import *
-
-
- class DateTimeEdit1(QWidget):
- def __init__(self):
- super(DateTimeEdit1, self).__init__()
- self.initUI()
-
- def initUI(self):
- # 垂直布局
- vlayout = QVBoxLayout()
- dateTimeEdit1 = QDateTimeEdit()
- dateTimeEdit2 = QDateTimeEdit(QDateTime.currentDateTimeUtc()) # 传入当前时间
-
- dateEdit = QDateTimeEdit(QDate.currentDate()) # 传入当前日期
- timeEdit = QDateTimeEdit(QTime.currentTime()) # 传入当前日期
-
- dateTimeEdit1.setDisplayFormat('yyyy-MM-dd HH:mm:ss')
- dateTimeEdit2.setDisplayFormat('yyyy/MM/dd HH:mm:ss')
-
- dateEdit.setDisplayFormat('yyyy.MM.dd')
- timeEdit.setDisplayFormat('HH:mm:ss')
-
- vlayout.addWidget(dateTimeEdit1)
- vlayout.addWidget(dateTimeEdit2)
- vlayout.addWidget(dateEdit)
- vlayout.addWidget(timeEdit)
-
- self.setLayout(vlayout)
- self.resize(300, 90)
- self.setWindowTitle('设置不同风格的日期和时间')
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = DateTimeEdit1()
- main.show()
- sys.exit(app.exec_())
方法 描述
setDisplayFormat 设置日期的时间格式
yyyy:代表年份,用4为数表示
MM:代表月份,取值范围01-12
dd:代表日,取值范围01-31
HH:代表小时,取值范围00-23
mm:代表分钟,取值范围00-59
ss:代表秒,取值范围00-59
setMinimumDate() 设置控件的最小日期
setMaximumDate() 设置控件的最大日期
time() 返回编辑的时间
date() 返回编辑的日期
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 21:55
- import sys
- from PyQt5.QtWidgets import *
-
-
- class Menu(QMainWindow):
- def __init__(self):
- super(Menu, self).__init__()
- bar = self.menuBar()
-
- file = bar.addMenu('文件') # 顶层菜单栏
- # 文件的子菜单(方法一:直接传文本,内部会自动创建动作QAction)
- file.addAction('新建')
-
- # 法二:自己用动作来创建子菜单
- save = QAction('保存', self) # 必须加self,代表在当前窗口加QAction
- save.setShortcut('Ctrl+S') # 快捷键
- file.addAction(save)
- quit = QAction('退出', self)
- file.addAction(quit)
-
- edit = bar.addMenu('Edit') # 顶层菜单
- edit.addAction('copy') # 子菜单
- edit.addAction('paste')
-
- save.triggered.connect(self.process)
-
- self.resize(400, 300)
-
- # 槽函数
- # 事件自动传给槽函数的一个实参,在本例具体指的是菜单项是否被选中,是一个bool类型的值
- def process(self, a):
- print(self.sender().text()) # 注意这里是self.而不是a.
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = Menu()
- main.show()
- sys.exit(app.exec_())
-
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 22:06
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtGui import *
- from PyQt5.QtCore import *
-
-
- class Toolbar(QMainWindow):
- def __init__(self):
- super(Toolbar, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('工具栏例子')
- self.resize(300, 200)
-
- tb1 = self.addToolBar('File') # 一行工具栏
- '''
- 工具栏默认按钮:只显示图标,将文本作为悬停提示
- 即鼠标悬停到图标上之后,提示就是下面的第二个参数
- '''
- new = QAction(QIcon('./csdnlogo.jpg'), '新建', self) # self代表放在当前窗口上
- tb1.addAction(new)
-
- open = QAction(QIcon('./csdnlogo.jpg'), '打开', self)
- tb1.addAction(open)
-
- save = QAction(QIcon('./csdnlogo.jpg'), '保存', self)
- tb1.addAction(save)
- '''
- 工具栏按钮有3种显示状态
- 1.只显示图标
- 2.只显示文本
- 3.同时显示文本和图标
- '''
- # 设置工具栏按钮显示状态:既显示文本又显示图标
- tb1.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) # 设置文本在图标的下方显示,还有好多,按ctrl查看自己试试
-
- tb2 = self.addToolBar('File1')
- new1 = QAction(QIcon('./csdnlogo.jpg'), '新建', self)
- tb2.addAction(new1)
- tb2.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
-
- tb1.actionTriggered.connect(self.toolbtnpressed)
- tb2.actionTriggered.connect(self.toolbtnpressed)
-
- def toolbtnpressed(self, a):
- print('按下的工具栏按钮是', a.text())
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = Toolbar()
- main.show()
- sys.exit(app.exec_())
-
用于显示状态信息,一般在窗口的最下方显示
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 22:16
- import sys
- from PyQt5.QtWidgets import *
-
-
- class Statusbar(QMainWindow):
- def __init__(self):
- super(Statusbar, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('状态栏演示')
- self.resize(300, 200)
-
- bar = self.menuBar() # 顶层菜单栏
- file = bar.addMenu('File') # 给菜单栏添加选项
- file.addAction('show') # 子菜单
-
- file.triggered.connect(self.processTrigger)
-
- self.setCentralWidget(QTextEdit()) # 多行输入
- self.statusBar = QStatusBar()
- self.setStatusBar(self.statusBar)
-
- def processTrigger(self, q):
- if q.text() == 'show':
- # 在状态栏上显示信息
- self.statusBar.showMessage(q.text() + '菜单被点击了', 5000) # 信息显示5秒
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = Statusbar()
- main.show()
- sys.exit(app.exec_())
-
输出都是以图像形式输出,输出到打印机
链接打印机开始打印 这里就不测试打印机了!
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 22:21
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5 import QtGui, QtPrintSupport
-
-
- class PrintSupport(QMainWindow):
- def __init__(self):
- super(PrintSupport, self).__init__()
- self.setGeometry(500, 200, 300, 300)
- self.btn = QPushButton('打印QTextEdit控件中的内容', self)
- self.btn.setGeometry(20, 20, 260, 30) # x,y,w,h
- self.editor = QTextEdit('默认文本', self)
- self.editor.setGeometry(20, 60, 260, 200)
-
- self.btn.clicked.connect(self.print)
-
- def print(self):
- # 打印机对象
- printer = QtPrintSupport.QPrinter()
- painter = QtGui.QPainter()
- # 将绘制的目标重定向到打印机上
- painter.begin(printer) # painter画在begin的参数上,即printer上,若是self,则画在当前窗口上
- # 获得多行输入控件editor的整个框架
- screen = self.editor.grab()
- # 从(10,10)开始将screen上的文字输出到打印机上
- # drawPixmap:从图像文件中提取 Pixmap 并将其显示在指定位置
- painter.drawPixmap(10, 10, screen)
- painter.end()
- print('print')
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = PrintSupport()
- main.show()
- sys.exit(app.exec_())
因为没有打印机 但是可以输出为pdf文档
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 22:26
- import sys
- from PyQt5.QtPrintSupport import QPrinter, QPageSetupDialog, QPrintDialog
- from PyQt5.QtWidgets import *
-
-
- class PrintDialog(QMainWindow):
- def __init__(self):
- super(PrintDialog, self).__init__()
- # 打印机对象
- self.printer = QPrinter()
- self.initUI()
-
- def initUI(self):
- self.setGeometry(300, 300, 500, 400)
- self.setWindowTitle('打印对话框')
-
- self.editor = QTextEdit(self)
- self.editor.setGeometry(20, 20, 300, 270)
-
- self.openButton = QPushButton('打开文件', self)
- self.openButton.move(350, 20)
-
- self.settingButton = QPushButton('打印设置', self)
- self.settingButton.move(350, 50)
-
- self.printButton = QPushButton('打印文档', self)
- self.printButton.move(350, 80)
-
- self.openButton.clicked.connect(self.openFile)
- self.settingButton.clicked.connect(self.showSettingDialog)
- self.printButton.clicked.connect(self.showPrintDialog)
-
- # 打开文件
- def openFile(self):
- fname = QFileDialog.getOpenFileName(self, '打开文本文件', './')
- print(fname)
- print(fname[0])
- if fname[0]:
- with open(fname[0], 'r', encoding='utf-8', errors='ignore') as f:
- self.editor.setText(f.read())
-
- # 显示打印设置对话框
- def showSettingDialog(self):
- printDialog = QPageSetupDialog(self.printer, self)
- printDialog.exec()
-
- # 显示打印对话框
- def showPrintDialog(self):
- printdailog = QPrintDialog(self.printer, self)
- if QDialog.Accepted == printdailog.exec():
- # 将editor里的文字输出到打印机中
- self.editor.print(self.printer)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = PrintDialog()
- main.show()
- sys.exit(app.exec_())
显示二维表数据(QTableVi ew控件)
数据源 Model
需要创建QTableView实例和一个数据源(Model) ,然后将两者关联,这个体系类似于MVC模式。
一个QTableView实例可以存放不同的数据源,一个数据源也可以对应不同的QTableView实例。
MVC: Model Viewer Controller 即将数据Model和前端视图Viewer分离,通过控制器Controller 来控制。
MVC的目的是将后端的数据和前端页面的耦合度降低。
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 22:36
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtGui import *
-
-
- class TableView(QWidget):
- def __init__(self):
- super(TableView, self).__init__()
- self.setWindowTitle('QTableView表格视图控件演示')
- self.resize(500, 300)
-
- self.model = QStandardItemModel(4, 3) # 二维表4行3列
- # 数据表的字段
- self.model.setHorizontalHeaderLabels(['id', 'name', 'age'])
-
- self.tableView = QTableView()
- # 关联QTableView控件和Model
- self.tableView.setModel(self.model)
-
- # 添加数据
- item11 = QStandardItem('1') # 一个QStandardItem就是一个单元格
- item12 = QStandardItem('Kobe')
- item13 = QStandardItem('24')
- self.model.setItem(0, 0, item11)
- self.model.setItem(0, 1, item12)
- self.model.setItem(0, 2, item13)
- # 可跳行添加数据
- item31 = QStandardItem('7')
- item32 = QStandardItem('Durant')
- item33 = QStandardItem('35')
- self.model.setItem(2, 0, item31)
- self.model.setItem(2, 1, item32)
- self.model.setItem(2, 2, item33)
-
- # 垂直布局
- layout = QVBoxLayout()
- layout.addWidget(self.tableView)
- self.setLayout(layout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = TableView()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 22:46
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import QStringListModel
-
-
- class ListView(QWidget):
- def __init__(self):
- super(ListView, self).__init__()
- self.setWindowTitle('ListView例子')
- self.resize(300, 270)
- layout = QVBoxLayout()
-
- listView = QListView()
- # 数据源
- listModel = QStringListModel()
- self.list = ['列表项1', '列表项2', '列表项3']
- listModel.setStringList(self.list)
-
- # 关联视图与数据源
- listView.setModel(listModel)
-
- listView.clicked.connect(self.clicked)
- layout.addWidget(listView)
-
- self.setLayout(layout)
-
- def clicked(self, item):
- QMessageBox.information(self, 'QListView', '您选择了:' + self.list[item.row()])
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = ListView()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 22:50
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import QStringListModel
-
- '''
- QListWidget是QListView的子类
- 添加了很多API,支持MVC模式,也支持非MVC模式,即数据直接添加到控件上
- '''
-
-
- class ListWidget(QMainWindow):
- def __init__(self):
- super(ListWidget, self).__init__()
- self.setWindowTitle('ListWidget例子')
- self.resize(300, 270)
-
- # 直接添加的方式适合少量的数据的时候
- self.listWidget = QListWidget()
- # self.listWidget.resize(300,120)
- self.listWidget.addItem('item1')
- self.listWidget.addItem('item2')
- self.listWidget.addItem('item3')
- self.listWidget.addItem('item4')
- self.listWidget.addItem('item5')
-
- self.listWidget.itemClicked.connect(self.clicked)
- # 设置中心控件之后,会铺满整个屏幕,无需再单独设置listWidget尺寸
- self.setCentralWidget(self.listWidget)
-
- def clicked(self, index):
- QMessageBox.information(self, 'ListWidget',
- '您选择了:' + self.listWidget.item(self.listWidget.row(index)).text())
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = ListWidget()
- main.show()
- sys.exit(app.exec_())
每一个Cell (单元格) 是一个QTableWidgetItem
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 22:52
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
-
- '''
- QTableWidget是QTableView的子类
- 添加了很多API,支持MVC模式,也支持非MVC模式,即数据直接添加到控件上
- '''
-
-
- class TableWidget(QWidget):
- def __init__(self):
- super(TableWidget, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('QTableWidget演示')
- self.resize(430, 230)
-
- layout = QHBoxLayout()
- tablewidget = QTableWidget()
- # 4行3列
- tablewidget.setRowCount(4)
- tablewidget.setColumnCount(3)
-
- tablewidget.setHorizontalHeaderLabels(['name', 'age', 'address'])
-
- nameItem = QTableWidgetItem('文龙')
- tablewidget.setItem(0, 0, nameItem)
- ageItem = QTableWidgetItem('23')
- tablewidget.setItem(0, 1, ageItem)
- addressItem = QTableWidgetItem('北京')
- tablewidget.setItem(0, 2, addressItem)
- # 禁止编辑
- tablewidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
- # 整行选择
- tablewidget.setSelectionBehavior(QAbstractItemView.SelectRows)
- # 调整列和行
- tablewidget.resizeColumnsToContents()
- tablewidget.resizeRowsToContents()
- # 隐藏表格头
- tablewidget.horizontalHeader().setVisible(False) # 隐藏水平方向的表格头
- # tablewidget.verticalHeader().setVisible(False) #隐藏垂直方向的表格头
- # 设置表格头内容
- tablewidget.setVerticalHeaderLabels(['a', 'b']) # 垂直方向表格头前两个设为a,b
- # 隐藏表格线
- tablewidget.setShowGrid(False)
-
- layout.addWidget(tablewidget)
- self.setLayout(layout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = TableWidget()
- main.show()
- sys.exit(app.exec_())
在单元格中放置控件
setItem:将文本放到单元格中
setCellWidget:将控件放到单元格中
setStyleSheet设置控件的样式(QSS)
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 22:57
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
-
- '''
- QTableWidget是QTableView的子类
- 添加了很多API,支持MVC模式,也支持非MVC模式,即数据直接添加到控件上
- '''
-
-
- class TableWidget2(QWidget):
- def __init__(self):
- super(TableWidget2, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('在单元格中放置控件')
- self.resize(430, 300)
-
- layout = QHBoxLayout()
- tableWidget = QTableWidget()
- # 4行3列
- tableWidget.setRowCount(4)
- tableWidget.setColumnCount(3)
-
- tableWidget.setHorizontalHeaderLabels(['name', 'age', 'weigh(kg)'])
-
- textItem = QTableWidgetItem('小明')
- # setItem:将文本放到单元格中
- tableWidget.setItem(0, 0, textItem)
-
- # 下拉框
- combox = QComboBox()
- combox.addItem('男')
- combox.addItem('女')
- # setStyleSheet设置控件的样式(QSS)(类似于web中的CSS),即Qt StyleSheet(n.样式表)
- combox.setStyleSheet('QComboBox{margin:3px};') # 设置控键距离上下左右的单元格的距离(距离)
- # setCellWidget:将控件放到单元格中
- tableWidget.setCellWidget(0, 1, combox)
-
- modifyButton = QPushButton('修改')
- # 默认是按下的状态
- modifyButton.setDown(True)
- modifyButton.setStyleSheet('QPushButton{margin:3px};')
- tableWidget.setCellWidget(0, 2, modifyButton)
-
- layout.addWidget(tableWidget)
- self.setLayout(layout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = TableWidget2()
- main.show()
- sys.exit(app.exec_())
在表格中快速定位到特定的行
1.数据的定位: findItems ,返回一个列表
2.如果找到了满足条件的单元格,会定位到单元格所在的行: setSliderPosition(row)
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 23:03
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
-
- class DataLocation(QWidget):
- def __init__(self):
- super(DataLocation, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('在表格中搜索Cell和行定位')
- self.resize(600, 800)
-
- layout = QHBoxLayout()
- tableWidget = QTableWidget()
- tableWidget.setRowCount(40)
- tableWidget.setColumnCount(4)
-
- for i in range(40):
- for j in range(4):
- itemContent = '(%d,%d)' % (i, j)
- tableWidget.setItem(i, j, QTableWidgetItem(itemContent))
- self.setLayout(layout)
- # 搜索满足条件的Cell
- text = '(13,1)'
- text1 = '(1,'
- # 参数一:要匹配的文本 ; 参数二:搜索模式,返回一个列表
- # items=tableWidget.findItems(text,Qt.MatchExactly)#搜索模式设为精确匹配,必须一模一样才行
- items = tableWidget.findItems(text1, Qt.MatchStartsWith) # 搜索模式为匹配以...为开头的字符串,这里看text1,即以(1,开头的的字符串
- length = len(items)
- if length > 0:
- print('匹配项个数:', len(items))
- for i in range(length):
- item = items[i]
- # 背景色
- item.setBackground(QBrush(QColor(0, 255, 0))) # rgb
- # 前景色,即文字的颜色
- item.setForeground(QBrush(QColor(255, 0, 0)))
- # 当前项所在的行
- row = item.row()
- # 定位到指定的行
- tableWidget.verticalScrollBar().setSliderPosition(row)
-
- layout.addWidget(tableWidget)
- self.setLayout(layout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = DataLocation()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 23:19
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
-
- class CellFontAndColor(QWidget):
- def __init__(self):
- super(CellFontAndColor, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('设置单元格字体和颜色')
- self.resize(430, 230)
-
- layout = QHBoxLayout()
- tableWidget = QTableWidget()
- tableWidget.setRowCount(4)
- tableWidget.setColumnCount(3)
-
- tableWidget.setHorizontalHeaderLabels(['name', 'sex', 'weigh(kg)'])
-
- newItem = QTableWidgetItem('小明') # 单元格的数据项
- newItem.setFont(QFont('Times', 14, QFont.Black)) # 字体,字号,颜色
- newItem.setForeground(QBrush(QColor(255, 0, 0)))
- tableWidget.setItem(0, 0, newItem)
-
- newItem = QTableWidgetItem('女')
- newItem.setForeground(QBrush(QColor(255, 255, 0)))
- newItem.setBackground(QBrush(QColor(0, 0, 255))) # rgb
- tableWidget.setItem(0, 1, newItem)
-
- newItem = QTableWidgetItem('100')
- newItem.setFont(QFont('Times', 20, QFont.Black))
- newItem.setForeground(QBrush(QColor(0, 0, 255)))
- tableWidget.setItem(0, 2, newItem)
-
- layout.addWidget(tableWidget)
- self.setLayout(layout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = CellFontAndColor()
- main.show()
- sys.exit(app.exec_())
按列排序
1.按哪一列排序
2.排序类型:升序或降序
sortItems( columnIndex,orderType)
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 23:23
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
-
- class CellFontAndColor(QWidget):
- def __init__(self):
- super(CellFontAndColor, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('设置单元格字体和颜色')
- self.resize(540, 230)
-
- layout = QHBoxLayout()
- self.tableWidget = QTableWidget() # 表格对象
- self.tableWidget.setRowCount(4)
- self.tableWidget.setColumnCount(3)
-
- self.tableWidget.setHorizontalHeaderLabels(['name', 'sex', 'weigh(kg)'])
-
- # 添加数据
- newItem = QTableWidgetItem('张三')
- self.tableWidget.setItem(0, 0, newItem)
- newItem = QTableWidgetItem('男')
- self.tableWidget.setItem(0, 1, newItem)
- newItem = QTableWidgetItem('165')
- self.tableWidget.setItem(0, 2, newItem)
-
- newItem = QTableWidgetItem('李四')
- self.tableWidget.setItem(1, 0, newItem)
- newItem = QTableWidgetItem('女')
- self.tableWidget.setItem(1, 1, newItem)
- newItem = QTableWidgetItem('120')
- self.tableWidget.setItem(1, 2, newItem)
-
- newItem = QTableWidgetItem('王五')
- self.tableWidget.setItem(2, 0, newItem)
- newItem = QTableWidgetItem('男')
- self.tableWidget.setItem(2, 1, newItem)
- newItem = QTableWidgetItem('130')
- self.tableWidget.setItem(2, 2, newItem)
-
- # 点击按钮排序
- self.btn = QPushButton('升序')
- self.btn.clicked.connect(self.order)
- # 常量
- self.orderType = Qt.DescendingOrder
-
- layout.addWidget(self.tableWidget)
- layout.addWidget(self.btn)
- self.setLayout(layout)
-
- # 升降序来回切换
- def order(self):
- if self.orderType == Qt.DescendingOrder:
- self.orderType = Qt.AscendingOrder
- self.btn.setText('降序') # 重命名按钮名,setText设置按钮显示文本
- else:
- self.orderType = Qt.DescendingOrder
- self.btn.setText('升序')
- # print(Qt.DescendingOrder)
- # print(self.orderType)
- self.tableWidget.sortItems(2, self.orderType) # 按照第三列的数据项排序
- # self.tableWidget.sortItems(2, Qt.DescendingOrder)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = CellFontAndColor()
- main.show()
- sys.exit(app.exec_())
setTextAlignment
Qt. AlignRight 右对齐 Qt.AlignBottom底端显示
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 23:29
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
-
- class CellTextAlignment(QWidget):
- def __init__(self):
- super(CellTextAlignment, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('设置单元格的文本对齐方式')
- self.resize(430, 230)
-
- layout = QHBoxLayout()
- # 表格对象
- tableWidget = QTableWidget()
- # 四行三列
- tableWidget.setRowCount(4)
- tableWidget.setColumnCount(3)
- # 设置表格字段
- tableWidget.setHorizontalHeaderLabels(['姓名', '性别', '体重(kg)'])
-
- newItem = QTableWidgetItem('小明')
- # 下面说的对齐与显示都是指在单元格中
- # 右对齐 底端显示,即右下,Qt.AlignRight默认是右上
- newItem.setTextAlignment(Qt.AlignRight | Qt.AlignBottom)
- tableWidget.setItem(0, 0, newItem)
- # 中心对齐,底部显示
- newItem = QTableWidgetItem('男')
- newItem.setTextAlignment(Qt.AlignCenter | Qt.AlignBottom)
- tableWidget.setItem(0, 1, newItem)
- newItem = QTableWidgetItem('190')
- newItem.setTextAlignment(Qt.AlignRight)
- tableWidget.setItem(0, 2, newItem)
-
- layout.addWidget(tableWidget)
- self.setLayout(layout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = CellTextAlignment()
- main.show()
- sys.exit(app.exec_())
setSpan(row, col ,要合并的行数,要合并的列数)
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 23:31
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
-
- class MergeCell(QWidget):
- def __init__(self):
- super(MergeCell, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('合并单元格')
- self.resize(430, 230)
-
- layout = QHBoxLayout()
- # 表格对象
- tableWidget = QTableWidget()
- # 四行三列
- tableWidget.setRowCount(4)
- tableWidget.setColumnCount(3)
- # 设置表格字段
- tableWidget.setHorizontalHeaderLabels(['姓名', '性别', '体重(kg)'])
-
- newItem = QTableWidgetItem('小明')
- tableWidget.setItem(0, 0, newItem)
- # setSpan(row, col, 要合并的行数,要合并的列数)
- tableWidget.setSpan(0, 0, 3, 1)
-
- newItem = QTableWidgetItem('男')
- tableWidget.setItem(0, 1, newItem)
- tableWidget.setSpan(0, 1, 2, 1)
-
- newItem = QTableWidgetItem('190')
- tableWidget.setItem(0, 2, newItem)
-
- newItem = QTableWidgetItem('test')
- tableWidget.setItem(2, 1, newItem)
- tableWidget.setSpan(2, 1, 1, 2)
-
- layout.addWidget(tableWidget)
- self.setLayout(layout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = MergeCell()
- main.show()
- sys.exit(app.exec_())
单元格大小可手动拖动改变大小,当字体设置很大时,运行之后显示的单元格大小可能不足够显示出文字,只会显示三个点省略,这时就要设置单元格尺寸了。
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 23:34
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
-
- class MergeCell(QWidget):
- def __init__(self):
- super(MergeCell, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('合并单元格')
- self.resize(600, 400)
-
- layout = QHBoxLayout()
- # 表格对象
- tableWidget = QTableWidget()
- # 四行三列
- tableWidget.setRowCount(4)
- tableWidget.setColumnCount(3)
- # 设置表格字段
- tableWidget.setHorizontalHeaderLabels(['姓名', '性别', '体重(kg)'])
-
- newItem = QTableWidgetItem('小明') # 单元格的数据项
- newItem.setFont(QFont('Times', 40, QFont.Black)) # 字体,字号,颜色
- newItem.setForeground(QBrush(QColor(255, 0, 0)))
- tableWidget.setItem(0, 0, newItem)
-
- newItem = QTableWidgetItem('女')
- newItem.setForeground(QBrush(QColor(255, 255, 0)))
- newItem.setBackground(QBrush(QColor(0, 0, 255))) # rgb
- tableWidget.setItem(0, 1, newItem)
-
- newItem = QTableWidgetItem('100')
- newItem.setFont(QFont('Times', 60, QFont.Black))
- newItem.setForeground(QBrush(QColor(0, 0, 255)))
- tableWidget.setItem(0, 2, newItem)
-
- tableWidget.setRowHeight(0, 120) # 设置第一行高度,三个数据项都在第一行上,第一行的单元格高度都变为120
- tableWidget.setColumnWidth(0, 150) # 设置第一列宽度
- tableWidget.setRowHeight(2, 200) # 设置第三行高度,注意这是第三行,而不是第三个单元格的高度!!!!!
- tableWidget.setColumnWidth(2, 180) # 设置第二列宽度
-
- layout.addWidget(tableWidget)
- self.setLayout(layout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = MergeCell()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 23:38
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
-
- class MergeCell(QWidget):
- def __init__(self):
- super(MergeCell, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('合并单元格')
- self.resize(600, 250)
-
- layout = QHBoxLayout()
- # 表格对象
- tableWidget = QTableWidget()
- # 四行四列
- tableWidget.setRowCount(4)
- tableWidget.setColumnCount(4)
- # 设置表格字段
- tableWidget.setHorizontalHeaderLabels(['姓名', '性别', '体重(kg)'])
-
- newItem = QTableWidgetItem('李宁')
- tableWidget.setItem(0, 0, newItem)
- newItem = QTableWidgetItem('男')
- tableWidget.setItem(0, 1, newItem)
- newItem = QTableWidgetItem('160')
- tableWidget.setItem(0, 2, newItem)
-
- newItem = QTableWidgetItem(QIcon('./and.png'), '背包')
- tableWidget.setItem(0, 3, newItem)
-
- layout.addWidget(tableWidget)
- self.setLayout(layout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = MergeCell()
- main.show()
- sys.exit(app.exec_())
setIconSize(QSize(width, height))
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 23:44
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
-
- class CellImageSize(QWidget):
- def __init__(self):
- super(CellImageSize, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('改变单元格中图片尺寸')
- self.resize(1000, 900)
-
- layout = QHBoxLayout()
- # 表格对象
- tableWidget = QTableWidget()
- # 设置单元格中图片大小
- tableWidget.setIconSize(QSize(300, 200))
- # 五行三列
- tableWidget.setRowCount(5)
- tableWidget.setColumnCount(3)
- # 设置表格字段
- tableWidget.setHorizontalHeaderLabels(['image1', 'image2', 'image3'])
- # 让列的宽度和图片的宽度相同
- for i in range(3):
- tableWidget.setColumnWidth(i, 300)
- # 让行的高度和图片的高度相同
- for i in range(5):
- tableWidget.setRowHeight(i, 200)
-
- for k in range(15):
- i = k / 3 # 行
- j = k % 3 # 列
- item = QTableWidgetItem()
- item.setIcon(QIcon('./csdn/csdn%d.png' % (k + 1)))
- tableWidget.setItem(i, j, item)
-
- layout.addWidget(tableWidget)
- self.setLayout(layout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = CellImageSize()
- main.show()
- sys.exit(app.exec_())
1.如何弹出菜单
2.如果在满足条件的情况下弹出菜单
QMenu. exec_()
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/23 23:56
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
-
- class CellImageSize(QWidget):
- def __init__(self):
- super(CellImageSize, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('在表格中显示上下文菜单')
- self.resize(500, 200)
-
- layout = QHBoxLayout()
- # 表格对象
- self.tableWidget = QTableWidget()
- # 五行三列
- self.tableWidget.setRowCount(4)
- self.tableWidget.setColumnCount(3)
- # 设置表格字段
- self.tableWidget.setHorizontalHeaderLabels(['name', 'sex', 'weigh'])
-
- # 添加数据
- newItem = QTableWidgetItem('小明')
- self.tableWidget.setItem(0, 0, newItem)
- newItem = QTableWidgetItem('男')
- self.tableWidget.setItem(0, 1, newItem)
- newItem = QTableWidgetItem('190')
- self.tableWidget.setItem(0, 2, newItem)
-
- newItem = QTableWidgetItem('小亮')
- self.tableWidget.setItem(1, 0, newItem)
- newItem = QTableWidgetItem('男')
- self.tableWidget.setItem(1, 1, newItem)
- newItem = QTableWidgetItem('100')
- self.tableWidget.setItem(1, 2, newItem)
-
- newItem = QTableWidgetItem('小红')
- self.tableWidget.setItem(2, 0, newItem)
- newItem = QTableWidgetItem('女')
- self.tableWidget.setItem(2, 1, newItem)
- newItem = QTableWidgetItem('90')
- self.tableWidget.setItem(2, 2, newItem)
-
- # 设置允许弹出上下文你菜单
- self.tableWidget.setContextMenuPolicy(Qt.CustomContextMenu)
- # 信号与槽
- self.tableWidget.customContextMenuRequested.connect(self.generateMenu)
-
- layout.addWidget(self.tableWidget)
- self.setLayout(layout)
-
- def generateMenu(self, pos):
- print('pos=', pos)
- for i in self.tableWidget.selectionModel().selection().indexes():
- rowNum = i.row()
- print('选择了第%d行' % (rowNum + 1))
- # 如果选择的行索引小于2,弹出上下文菜单
- if rowNum < 2:
- menu = QMenu()
- item1 = menu.addAction('菜单项1') # 一个动作
- # print(type(item1))
- item2 = menu.addAction('菜单项2')
- item3 = menu.addAction('菜单项3')
- # pos是相对于整个屏幕的坐标,所以要转换为窗口坐标
- screenPos = self.tableWidget.mapToGlobal(pos)
- print('screenPos=', screenPos)
- # 被阻塞
- action = menu.exec_(screenPos)
- if action == item1:
- print('选择了第一个菜单项', self.tableWidget.item(rowNum, 0).text(),
- self.tableWidget.item(rowNum, 1).text(),
- self.tableWidget.item(rowNum, 2).text())
- elif action == item2:
- print('选择了第二个菜单项', self.tableWidget.item(rowNum, 0).text(),
- self.tableWidget.item(rowNum, 1).text(),
- self.tableWidget.item(rowNum, 2).text())
- elif action == item3:
- print('选择了第三个菜单项', self.tableWidget.item(rowNum, 0).text(),
- self.tableWidget.item(rowNum, 1).text(),
- self.tableWidget.item(rowNum, 2).text())
- else:
- return
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = CellImageSize()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 10:00
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
-
- class BasicTreeWidget(QMainWindow):
- def __init__(self, parent=None):
- super(BasicTreeWidget, self).__init__(parent)
- self.setWindowTitle('树控件(QTreeWidget)的基本用法')
- self.resize(500, 300)
-
- # 树
- self.tree = QTreeWidget()
- # 为树控件指定列数
- self.tree.setColumnCount(2)
- # 指定列标签
- self.tree.setHeaderLabels(['Key', 'Value'])
-
- # 根节点
- root = QTreeWidgetItem(self.tree)
- root.setText(0, '根节点') # 0代表第一列,即Key列
- root.setIcon(0, QIcon('./and.png')) # 为节点设置图标
- self.tree.setColumnWidth(0, 200) # 第一列列宽设为200
-
- # 添加子节点1
- child1 = QTreeWidgetItem(root)
- child1.setText(0, '子节点1') # 第一列Key为 子节点1
- child1.setText(1, '子节点1的数据') # 第二列Value为 子节点1的数据
- child1.setIcon(0, QIcon('./and.png'))
- # 设置子节点1开启复选框状态
- child1.setCheckState(0, Qt.Checked)
-
- # 添加子节点2
- child2 = QTreeWidgetItem(root)
- child2.setText(0, '子节点2')
- child2.setIcon(0, QIcon('./and.png'))
-
- # 为child2添加一个子节点
- child3 = QTreeWidgetItem(child2)
- child3.setText(0, '子节点2-1')
- child3.setText(1, '新的值')
- child3.setIcon(0, QIcon('./and.png'))
-
- # 默认所有节点都处于展开状态
- self.tree.expandAll()
-
- # 将树控件设为中心控件,即树控件会自动铺满整个屏幕
- self.setCentralWidget(self.tree)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = BasicTreeWidget()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 10:08
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
-
- class TreeEvent(QMainWindow):
- def __init__(self, parent=None):
- super(TreeEvent, self).__init__(parent)
- self.setWindowTitle('为树添加响应事件')
- self.resize(400, 300)
-
- # 树
- self.tree = QTreeWidget()
- # 为树控件指定列数
- self.tree.setColumnCount(2)
- # 指定列标签
- self.tree.setHeaderLabels(['Key', 'Value'])
-
- # 根节点
- root = QTreeWidgetItem(self.tree)
- root.setText(0, 'root') # 0代表第一列,即Key列,值为root
- root.setText(1, '0')
-
- # 添加子节点child1
- child1 = QTreeWidgetItem(root)
- child1.setText(0, 'child1')
- child1.setText(1, '1')
-
- # 添加子节点child2
- child2 = QTreeWidgetItem(root)
- child2.setText(0, 'child2')
- child2.setText(1, '2')
-
- # 为child2添加一个子节点child3
- child3 = QTreeWidgetItem(child2)
- child3.setText(0, 'child3')
- child3.setText(1, '3')
-
- # 信号和槽
- self.tree.clicked.connect(self.onTreeClicked)
-
- # 将树控件设为中心控件,即树控件会自动铺满整个屏幕
- self.setCentralWidget(self.tree)
-
- def onTreeClicked(self, index): # index是被点击节点的索引
- item = self.tree.currentItem() # 获得当前单击项
- print('当前处于第%d行' % index.row()) # 输出当前行(自己父节点的第几个值)
- print('key=%s,value=%s' % (item.text(0), item.text(1)))
- print()
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = TreeEvent()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 10:14
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
-
- class ModifyTree(QWidget):
- def __init__(self, parent=None):
- super(ModifyTree, self).__init__(parent)
- self.setWindowTitle('增加修改和删除树控件中的节点')
- self.resize(400, 300)
-
- operatorLayout = QHBoxLayout() # 水平布局
-
- addBtn = QPushButton('添加节点')
- updateBtn = QPushButton('修改节点')
- deleteBtn = QPushButton('删除节点')
-
- operatorLayout.addWidget(addBtn)
- operatorLayout.addWidget(updateBtn)
- operatorLayout.addWidget(deleteBtn)
-
- addBtn.clicked.connect(self.addNode)
- updateBtn.clicked.connect(self.updateNode)
- deleteBtn.clicked.connect(self.deleteNode)
-
- # 树
- self.tree = QTreeWidget()
- # 为树控件指定列数
- self.tree.setColumnCount(2)
- # 指定列标签
- self.tree.setHeaderLabels(['Key', 'Value'])
-
- # 根节点
- root = QTreeWidgetItem(self.tree)
- root.setText(0, 'root') # 0代表第一列,即Key列,值为root
- root.setText(1, '0')
-
- # 添加子节点child1
- child1 = QTreeWidgetItem(root)
- child1.setText(0, 'child1')
- child1.setText(1, '1')
-
- # 添加子节点child2
- child2 = QTreeWidgetItem(root)
- child2.setText(0, 'child2')
- child2.setText(1, '2')
-
- # 为child2添加一个子节点child3
- child3 = QTreeWidgetItem(child2)
- child3.setText(0, 'child3')
- child3.setText(1, '3')
-
- # 信号和槽
- self.tree.clicked.connect(self.onTreeClicked)
-
- mainLayout = QVBoxLayout(self)
- mainLayout.addLayout(operatorLayout)
- mainLayout.addWidget(self.tree)
- self.setLayout(mainLayout)
-
- def onTreeClicked(self, index): # index是被点击节点的索引
- item = self.tree.currentItem() # 获得当前单击项
- print('当前处于第%d行' % index.row()) # 输出当前行(自己父节点的第几个值)
- print('key=%s,value=%s' % (item.text(0), item.text(1)))
- print()
-
- def addNode(self):
- print('添加节点')
- item = self.tree.currentItem() # 获得当前节点
- print('当前节点是:', item)
- node = QTreeWidgetItem(item)
- node.setText(0, '新节点')
- node.setText(1, '新值')
-
- def updateNode(self):
- print('修改节点')
- item = self.tree.currentItem()
- item.setText(0, '修改节点')
- item.setText(1, '值已经被修改')
-
- def deleteNode(self):
- print('删除节点')
- # 防止item是root时,root无父结点报错,要使用下面的写法
- rootFather = self.tree.invisibleRootItem() # 获得根节点root的不可见的父节点
- for item in self.tree.selectedItems():
- # 父节点不为空
- (item.parent() or rootFather).removeChild(item)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = ModifyTree()
- main.show()
- sys.exit(app.exec_())
一般复杂的树控件用QTreeView来写
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 10:21
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
-
- # 显示目录结构的模型
- model = QDirModel()
- tree = QTreeView()
- tree.setModel(model)
- tree.setWindowTitle('QTreeView')
- tree.resize(600, 400)
- tree.show()
-
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 10:25
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
-
- class TabWidget(QTabWidget): # 直接一整个屏幕就是一个选项卡窗口
- def __init__(self, parent=None):
- super(TabWidget, self).__init__(parent)
- self.setWindowTitle('选项卡控件:QTabWidget')
- self.resize(400, 200)
- # 创建用于显示控件的窗口
- self.tab1 = QWidget()
- self.tab2 = QWidget()
- self.tab3 = QWidget()
- # 将窗口和选项卡绑定
- self.addTab(self.tab1, '选项卡1')
- self.addTab(self.tab2, '选项卡2')
- self.addTab(self.tab3, '选项卡3')
-
- self.tab1UI()
- self.tab2UI()
- self.tab3UI()
-
- def tab1UI(self):
- # 表单布局
- layout = QFormLayout()
- layout.addRow('姓名', QLineEdit())
- layout.addRow('地址', QLineEdit())
- # 将第一个选项卡窗口重命名
- self.setTabText(0, '联系方式')
- self.tab1.setLayout(layout) # 别忘了tab1就是一个窗口
-
- 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)
- main = TabWidget()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 10:30
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
-
- class StackedExample(QWidget): # 直接一整个屏幕就是一个选项卡窗口
- def __init__(self, parent=None):
- super(StackedExample, self).__init__(parent)
- self.setWindowTitle('堆栈窗口控件:QStackedWidget')
- # self.resize(400,200)
- self.setGeometry(800, 450, 10, 10)
- # 列表控件
- self.list = QListWidget()
- self.list.insertItem(0, '联系方式')
- self.list.insertItem(1, '个人信息')
- self.list.insertItem(2, '教育程度')
-
- self.stack1 = QWidget()
- self.stack2 = QWidget()
- self.stack3 = QWidget()
-
- self.tab1UI()
- self.tab2UI()
- self.tab3UI()
- # 堆栈窗口控件对象
- self.stack = QStackedWidget()
- self.stack.addWidget(self.stack1)
- self.stack.addWidget(self.stack2)
- self.stack.addWidget(self.stack3)
-
- self.list.currentRowChanged.connect(self.display)
-
- hbox = QHBoxLayout()
- hbox.addWidget(self.list)
- hbox.addWidget(self.stack)
- self.setLayout(hbox)
-
- def tab1UI(self):
- # 表单布局
- layout = QFormLayout()
- layout.addRow('姓名', QLineEdit())
- layout.addRow('地址', QLineEdit())
- self.stack1.setLayout(layout) # 别忘了tab1就是一个窗口
-
- def tab2UI(self):
- layout = QFormLayout()
- sex = QHBoxLayout() # 水平布局,横向排列
- # 单选框
- sex.addWidget(QRadioButton('男'))
- sex.addWidget(QRadioButton('女'))
- layout.addRow(QLabel('性别'), sex)
- layout.addRow('生日', QLineEdit())
- self.stack2.setLayout(layout)
-
- def tab3UI(self):
- layout = QHBoxLayout()
- layout.addWidget(QLabel('科目'))
- # 复选框
- layout.addWidget(QCheckBox('物理'))
- layout.addWidget(QCheckBox('高数'))
- self.stack3.setLayout(layout)
-
- def display(self, index):
- # 通过索引来切换页面
- self.stack.setCurrentIndex(index)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = StackedExample()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 10:35
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
-
- class DockDemo(QMainWindow): # 直接一整个屏幕就是一个选项卡窗口
- def __init__(self, parent=None):
- super(DockDemo, self).__init__(parent)
- self.setWindowTitle('停靠控件(QDockWidget)')
- self.setGeometry(800, 450, 500, 500) # x,y,w,h
- # self.resize(400, 200)
-
- layout = QHBoxLayout()
- # 停靠控件对象
- 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.setCentralWidget(QLineEdit('单行输入'))
- # 设置一开始就是悬浮状态
- self.items.setFloating(True)
-
- # 在窗口上设置停靠控件,且悬浮在右侧
- self.addDockWidget(Qt.RightDockWidgetArea, self.items)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = DockDemo()
- main.show()
- sys.exit(app.exec_())
相当于窗口的容器,里面可以有很多子窗口,但子窗口只能在这里面移动。
需要的类:
容纳多文档:QMdiArea
子窗口: QMdiSubWindow
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 10:44
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
-
- class MultiWindows(QMainWindow): # 直接一整个屏幕就是一个选项卡窗口
- count = 0 # 记录当前有多少个菜单项
-
- def __init__(self, parent=None):
- super(MultiWindows, self).__init__(parent)
- self.setWindowTitle('容纳多文档的窗口')
- self.setGeometry(800, 450, 500, 400) # x,y,w,h
-
- # 容纳多文档容器对象
- self.mdi = QMdiArea()
-
- bar = self.menuBar()
- file = bar.addMenu('File')
- file.addAction('New')
- file.addAction('cascade') # 重叠
- file.addAction('Tiled') # 平铺
-
- file.triggered.connect(self.windowAction)
-
- self.setCentralWidget(self.mdi)
-
- def windowAction(self, q): # q是当前的单击菜单项,通过按钮名来进行不同的操作
- if q.text() == 'New':
- self.count = self.count + 1
- # 子窗口对象
- sub = QMdiSubWindow()
- sub.setWidget(QTextEdit())
- sub.setWindowTitle('子窗口' + str(self.count))
- self.mdi.addSubWindow(sub)
- sub.show()
- # 下面两个是对mdi中已有的窗口排布进行操作,而不是生成窗口
- elif q.text() == 'cascade':
- self.mdi.cascadeSubWindows()
- elif q.text() == 'Tiled':
- self.mdi.tileSubWindows()
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = MultiWindows()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 10:52
- from PyQt5.QtWidgets import *
- from PyQt5.QtGui import *
- from PyQt5.QtCore import *
- import sys
-
-
- class ScrollBar(QWidget):
- def __init__(self):
- super(ScrollBar, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setWindowTitle('滚动条控件演示')
- self.setGeometry(400, 300, 300, 500)
- # 水平布局
- hbox = QHBoxLayout()
-
- # 定义控件
- self.label = QLabel('拖动滚动条去改变文字颜色')
-
- self.scrollbar1 = QScrollBar() # 滚动条
- self.scrollbar1.setMaximum(255) # 滚动条最大值
- # 信号与槽
- self.scrollbar1.sliderMoved.connect(self.sliderMoved)
-
- self.scrollbar2 = QScrollBar()
- self.scrollbar2.setMaximum(255)
- self.scrollbar2.sliderMoved.connect(self.sliderMoved)
-
- self.scrollbar3 = QScrollBar()
- self.scrollbar3.setMaximum(255)
- self.scrollbar3.sliderMoved.connect(self.sliderMoved)
-
- self.scrollbar4 = QScrollBar()
- self.scrollbar4.setMaximum(255)
- self.scrollbar4.sliderMoved.connect(self.sliderMoved1)
-
- # 向布局中添加控件
- hbox.addWidget(self.label)
- hbox.addWidget(self.scrollbar1)
- hbox.addWidget(self.scrollbar2)
- hbox.addWidget(self.scrollbar3)
- hbox.addWidget(self.scrollbar4)
-
- self.setLayout(hbox)
- # 获得标签的纵坐标
- self.y = self.label.pos().y()
-
- def sliderMoved(self):
- print(self.scrollbar1.value(), self.scrollbar2.value(), self.scrollbar3.value())
- # 调色版
- palette = QPalette()
- # 最后一个参数是透明度
- c = QColor(self.scrollbar1.value(), self.scrollbar2.value(), self.scrollbar3.value(), 255)
- # 参数一:QPalette.Foreground设置前景色,即标签的颜色 参数2:颜色
- palette.setColor(QPalette.Foreground, c)
- self.label.setPalette(palette)
-
- def sliderMoved1(self):
- # 向下移动标签
- self.label.move(self.label.x(), self.y + self.scrollbar4.value())
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = ScrollBar()
- main.show()
- sys.exit(app.exec_())
QTimer定时器,适用于多任务,即每隔一定的时间会调用一次
QThread:完成单个任务可以使用这个
多线程:用于同时完成多个任务
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 10:57
- import sys
- from PyQt5.QtGui import *
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
-
-
- class showTime(QWidget):
- def __init__(self, parent=None):
- super(showTime, self).__init__(parent)
- self.setWindowTitle('动态显示当前时间')
-
- self.label = QLabel('显示当前时间')
- self.startBtn = QPushButton('开始')
- self.endBtn = QPushButton('结束')
- # 栅格布局
- layout = QGridLayout()
-
- # 计时器对象
- self.timer = QTimer()
- self.timer.timeout.connect(self.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()
- # dddd是星期几
- timeDispaly = time.toString('yyyy-MM-dd hh:mm:ss dddd')
- # 将标签设置成当前时间
- self.label.setText(timeDispaly)
-
- def startTimer(self):
- # 参数是时间间隔,1000毫秒
- self.timer.start(1000)
- 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)
- main = showTime()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 11:05
- import sys
- from PyQt5.QtGui import *
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- label = QLabel('<font color=red size=140><b>Hello World,窗口在5秒后自动关闭!</b></font>')
- # setWindowFlag设置窗口属性:启动画面,无框架
- label.setWindowFlags(Qt.SplashScreen | Qt.FramelessWindowHint)
- label.show()
- # 5秒之后退出整个程序
- QTimer.singleShot(5000, app.quit)
- sys.exit(app.exec_())
-
用到自定义信号,之前用到的信号都是系统已经定义好的,这里需要自己再定义一个。
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 11:09
- import sys
- from PyQt5.QtGui import *
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
-
- # 全局变量,当前计数从0开始
- sec = 0
-
-
- class WorkThread(QThread): # 继承QThread类
- # 每隔一秒发送一次信号,pyqtSignal()用来定义信号的
- timer = pyqtSignal()
- # 计数完成后发送一次信号
- end = pyqtSignal()
-
- def run(self):
- while True:
- self.sleep(1) # 休眠一秒
- if sec == 5:
- self.end.emit() # 发送end信号,emit()用来发送信号
- break
- self.timer.emit() # 发送timer信号
-
-
- class Counter(QWidget):
- def __init__(self, parent=None):
- super(Counter, self).__init__(parent)
-
- self.setWindowTitle('使用线程类(QThread)编写计数器')
- self.resize(300, 120)
-
- layout = QVBoxLayout() # 垂直布局
- # 数码管
- self.lcdNumber = QLCDNumber()
- layout.addWidget(self.lcdNumber)
-
- btn = QPushButton('开始计数')
- layout.addWidget(btn)
-
- self.workThread = WorkThread()
-
- self.workThread.timer.connect(self.countTime)
- self.workThread.end.connect(self.end)
- btn.clicked.connect(self.work)
-
- self.setLayout(layout)
-
- def countTime(self):
- global sec # 声明一下是全局变量
- sec += 1
- self.lcdNumber.display(sec)
-
- def end(self):
- QMessageBox.information(self, '消息', '计数结束', QMessageBox.Ok)
-
- def work(self):
- self.workThread.start()
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = Counter()
- main.show()
- sys.exit(app.exec_())
PyQt5和web的交互技术
同时使用Python和web开发程序,混合开发
Python+JavaScript+Html+CSS
运行报错问题:
from PyQt5.QtWebEngineWidgets import *
ImportError: DLL load failed while importing QtWebEngineWidgets: 找不到指定的模块。
CSDN和百度了很多
我的解决方案是:将python3.9版本改为3.6版本 想着还是python过高的原因
右键运行
test.html Html文件
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>测试页面</title>
- </head>
- <body>
- <h1>Hello PyQt5</h1>
- <h2>Hello PyQt5</h2>
- <h3>Hello PyQt5</h3>
- <h4>Hello PyQt5</h4>
- </body>
- </html>
localHTML Py文件
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 12:52
- import sys
- import os
- from PyQt5.QtWebEngineWidgets import QWebEngineView
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
-
- class localHTML(QMainWindow):
- def __init__(self, parent=None):
- super(localHTML, self).__init__(parent)
- self.setWindowTitle('装载本地Web页面')
- self.setGeometry(5, 30, 1355, 730)
- # os.getcwd()是获取当前路径
- print(os.getcwd())
- url = os.getcwd() + '/test.html'
- self.browser = QWebEngineView()
- # QUrl.fromLocalFile(url)
- self.browser.load(QUrl.fromLocalFile(url))
- self.setCentralWidget(self.browser)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = localHTML()
- main.show()
- sys.exit(app.exec_())
将web页面的代码硬编码到代码里面,然后显示
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 12:58
- import sys
- import os
- from PyQt5.QtWebEngineWidgets import QWebEngineView
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
-
-
- class innerHTML(QMainWindow):
- def __init__(self, parent=None):
- super(innerHTML, self).__init__(parent)
- self.setWindowTitle('装载本地Web页面')
- self.setGeometry(5, 30, 1355, 730)
- self.browser = QWebEngineView()
- # 直接嵌入页面源码
- self.browser.setHtml('''
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>测试页面</title>
- </head>
- <body>
- <h1>Hello PyQt5</h1>
- <h2>Hello PyQt5</h2>
- <h3>Hello PyQt5</h3>
- <h4>Hello PyQt5</h4>
- </body>
- </html>
- ''')
- self.setCentralWidget(self.browser)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = innerHTML()
- main.show()
- sys.exit(app.exec_())
PyQt5和JavaScript交互
什么叫交互
PyQt5 <-> JavaScriptPyQt5调用JavaScript的函数,然后JavaScript的函数返回了值给PyQt5。
运行结果:功能:分别输入First name和Last name,然后 PyQt5调用JavaScript的函数,返回全名。
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 13:14
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- from PyQt5.QtWebEngineWidgets import *
- import sys
- import os
-
-
- class WebEngineView(QWidget):
- """
- PyQt5调用JavaScript代码
- PyQt5和JavaScrip交互
- 什么叫交互
- PyQt5<->JavaScript 即互相调用内部的函数
- """
-
- def __init__(self):
- super(WebEngineView, self).__init__()
- self.setWindowTitle('PyQt5调用JavaScript')
- self.setGeometry(5, 30, 1355, 730)
-
- self.layout = QVBoxLayout()
- self.setLayout(self.layout)
-
- self.browser = QWebEngineView()
- url = os.getcwd() + '/pyqt5calljs.html'
- self.browser.load(QUrl.fromLocalFile(url))
- self.layout.addWidget(self.browser)
-
- button = QPushButton('设置全名')
- button.clicked.connect(self.fullname)
- self.layout.addWidget(button)
-
- # 接受js返回值 即pyqt5calljs.html文件中的fullname函数返回值
- def js_callback(self, result):
- print(result)
-
- def fullname(self):
- self.value = 'hello world'
- self.browser.page().runJavaScript('fullname("' + self.value + '");', self.js_callback)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = WebEngineView()
- print(main.__doc__)
- main.show()
- sys.exit(app.exec_())
-
阶乘小知识:
阶乘是基斯顿·卡曼(Christian Kramp,1760~1826)于 1808 年发明的运算符号,是数学术语。
一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且0的阶乘为1。自然数n的阶乘写作n!。1808年,基斯顿·卡曼引进这个表示法。
阶乘指从1乘以2乘以3乘以4一直乘到所要求的数。
例如所要求的数是4,则阶乘式是1×2×3×4,得到的积是24,24就是4的阶乘。 例如所要求的数是6,则阶乘式是1×2×3×……×6,得到的积是720,720就是6的阶乘。例如所要求的数是n,则阶乘式是1×2×3×……×n,设得到的积是x,x就是n的阶乘。
将Python的一个对象映射到JavaScript中
将槽函数映射到JavaScript中总共有四个文件:
文件1 pyqt5calljs.html
文件2 js调用py文件(js_call_py.html)
文件3 阶乘功能类(factorial.py)
文件4 调用类(PyFactorial.py)
对应的pyqt5calljs.html文件如下:
qwebchannel.js
- /****************************************************************************
- **
- ** Copyright (C) 2015 The Qt Company Ltd.
- ** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
- ** Contact: http://www.qt.io/licensing/
- **
- ** This file is part of the QtWebChannel module of the Qt Toolkit.
- **
- ** $QT_BEGIN_LICENSE:LGPL21$
- ** Commercial License Usage
- ** Licensees holding valid commercial Qt licenses may use this file in
- ** accordance with the commercial license agreement provided with the
- ** Software or, alternatively, in accordance with the terms contained in
- ** a written agreement between you and The Qt Company. For licensing terms
- ** and conditions see http://www.qt.io/terms-conditions. For further
- ** information use the contact form at http://www.qt.io/contact-us.
- **
- ** GNU Lesser General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 or version 3 as published by the Free
- ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
- ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
- ** following information to ensure the GNU Lesser General Public License
- ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
- ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
- **
- ** As a special exception, The Qt Company gives you certain additional
- ** rights. These rights are described in The Qt Company LGPL Exception
- ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
- **
- ** $QT_END_LICENSE$
- **
- ****************************************************************************/
- "use strict";
-
- var QWebChannelMessageTypes = {
- signal: 1,
- propertyUpdate: 2,
- init: 3,
- idle: 4,
- debug: 5,
- invokeMethod: 6,
- connectToSignal: 7,
- disconnectFromSignal: 8,
- setProperty: 9,
- response: 10,
- };
-
- var QWebChannel = function(transport, initCallback)
- {
- if (typeof transport !== "object" || typeof transport.send !== "function") {
- console.error("The QWebChannel expects a transport object with a send function and onmessage callback property." +
- " Given is: transport: " + typeof(transport) + ", transport.send: " + typeof(transport.send));
- return;
- }
-
- var channel = this;
- this.transport = transport;
-
- this.send = function(data)
- {
- if (typeof(data) !== "string") {
- data = JSON.stringify(data);
- }
- channel.transport.send(data);
- }
-
- this.transport.onmessage = function(message)
- {
- var data = message.data;
- if (typeof data === "string") {
- data = JSON.parse(data);
- }
- switch (data.type) {
- case QWebChannelMessageTypes.signal:
- channel.handleSignal(data);
- break;
- case QWebChannelMessageTypes.response:
- channel.handleResponse(data);
- break;
- case QWebChannelMessageTypes.propertyUpdate:
- channel.handlePropertyUpdate(data);
- break;
- default:
- console.error("invalid message received:", message.data);
- break;
- }
- }
-
- this.execCallbacks = {};
- this.execId = 0;
- this.exec = function(data, callback)
- {
- if (!callback) {
- // if no callback is given, send directly
- channel.send(data);
- return;
- }
- if (channel.execId === Number.MAX_VALUE) {
- // wrap
- channel.execId = Number.MIN_VALUE;
- }
- if (data.hasOwnProperty("id")) {
- console.error("Cannot exec message with property id: " + JSON.stringify(data));
- return;
- }
- data.id = channel.execId++;
- channel.execCallbacks[data.id] = callback;
- channel.send(data);
- };
-
- this.objects = {};
-
- this.handleSignal = function(message)
- {
- var object = channel.objects[message.object];
- if (object) {
- object.signalEmitted(message.signal, message.args);
- } else {
- console.warn("Unhandled signal: " + message.object + "::" + message.signal);
- }
- }
-
- this.handleResponse = function(message)
- {
- if (!message.hasOwnProperty("id")) {
- console.error("Invalid response message received: ", JSON.stringify(message));
- return;
- }
- channel.execCallbacks[message.id](message.data);
- delete channel.execCallbacks[message.id];
- }
-
- this.handlePropertyUpdate = function(message)
- {
- for (var i in message.data) {
- var data = message.data[i];
- var object = channel.objects[data.object];
- if (object) {
- object.propertyUpdate(data.signals, data.properties);
- } else {
- console.warn("Unhandled property update: " + data.object + "::" + data.signal);
- }
- }
- channel.exec({type: QWebChannelMessageTypes.idle});
- }
-
- this.debug = function(message)
- {
- channel.send({type: QWebChannelMessageTypes.debug, data: message});
- };
-
- channel.exec({type: QWebChannelMessageTypes.init}, function(data) {
- for (var objectName in data) {
- var object = new QObject(objectName, data[objectName], channel);
- }
- // now unwrap properties, which might reference other registered objects
- for (var objectName in channel.objects) {
- channel.objects[objectName].unwrapProperties();
- }
- if (initCallback) {
- initCallback(channel);
- }
- channel.exec({type: QWebChannelMessageTypes.idle});
- });
- };
-
- function QObject(name, data, webChannel)
- {
- this.__id__ = name;
- webChannel.objects[name] = this;
-
- // List of callbacks that get invoked upon signal emission
- this.__objectSignals__ = {};
-
- // Cache of all properties, updated when a notify signal is emitted
- this.__propertyCache__ = {};
-
- var object = this;
-
- // ----------------------------------------------------------------------
-
- this.unwrapQObject = function(response)
- {
- if (response instanceof Array) {
- // support list of objects
- var ret = new Array(response.length);
- for (var i = 0; i < response.length; ++i) {
- ret[i] = object.unwrapQObject(response[i]);
- }
- return ret;
- }
- if (!response
- || !response["__QObject*__"]
- || response.id === undefined) {
- return response;
- }
-
- var objectId = response.id;
- if (webChannel.objects[objectId])
- return webChannel.objects[objectId];
-
- if (!response.data) {
- console.error("Cannot unwrap unknown QObject " + objectId + " without data.");
- return;
- }
-
- var qObject = new QObject( objectId, response.data, webChannel );
- qObject.destroyed.connect(function() {
- if (webChannel.objects[objectId] === qObject) {
- delete webChannel.objects[objectId];
- // reset the now deleted QObject to an empty {} object
- // just assigning {} though would not have the desired effect, but the
- // below also ensures all external references will see the empty map
- // NOTE: this detour is necessary to workaround QTBUG-40021
- var propertyNames = [];
- for (var propertyName in qObject) {
- propertyNames.push(propertyName);
- }
- for (var idx in propertyNames) {
- delete qObject[propertyNames[idx]];
- }
- }
- });
- // here we are already initialized, and thus must directly unwrap the properties
- qObject.unwrapProperties();
- return qObject;
- }
-
- this.unwrapProperties = function()
- {
- for (var propertyIdx in object.__propertyCache__) {
- object.__propertyCache__[propertyIdx] = object.unwrapQObject(object.__propertyCache__[propertyIdx]);
- }
- }
-
- function addSignal(signalData, isPropertyNotifySignal)
- {
- var signalName = signalData[0];
- var signalIndex = signalData[1];
- object[signalName] = {
- connect: function(callback) {
- if (typeof(callback) !== "function") {
- console.error("Bad callback given to connect to signal " + signalName);
- return;
- }
-
- object.__objectSignals__[signalIndex] = object.__objectSignals__[signalIndex] || [];
- object.__objectSignals__[signalIndex].push(callback);
-
- if (!isPropertyNotifySignal && signalName !== "destroyed") {
- // only required for "pure" signals, handled separately for properties in propertyUpdate
- // also note that we always get notified about the destroyed signal
- webChannel.exec({
- type: QWebChannelMessageTypes.connectToSignal,
- object: object.__id__,
- signal: signalIndex
- });
- }
- },
- disconnect: function(callback) {
- if (typeof(callback) !== "function") {
- console.error("Bad callback given to disconnect from signal " + signalName);
- return;
- }
- object.__objectSignals__[signalIndex] = object.__objectSignals__[signalIndex] || [];
- var idx = object.__objectSignals__[signalIndex].indexOf(callback);
- if (idx === -1) {
- console.error("Cannot find connection of signal " + signalName + " to " + callback.name);
- return;
- }
- object.__objectSignals__[signalIndex].splice(idx, 1);
- if (!isPropertyNotifySignal && object.__objectSignals__[signalIndex].length === 0) {
- // only required for "pure" signals, handled separately for properties in propertyUpdate
- webChannel.exec({
- type: QWebChannelMessageTypes.disconnectFromSignal,
- object: object.__id__,
- signal: signalIndex
- });
- }
- }
- };
- }
-
- /**
- * Invokes all callbacks for the given signalname. Also works for property notify callbacks.
- */
- function invokeSignalCallbacks(signalName, signalArgs)
- {
- var connections = object.__objectSignals__[signalName];
- if (connections) {
- connections.forEach(function(callback) {
- callback.apply(callback, signalArgs);
- });
- }
- }
-
- this.propertyUpdate = function(signals, propertyMap)
- {
- // update property cache
- for (var propertyIndex in propertyMap) {
- var propertyValue = propertyMap[propertyIndex];
- object.__propertyCache__[propertyIndex] = propertyValue;
- }
-
- for (var signalName in signals) {
- // Invoke all callbacks, as signalEmitted() does not. This ensures the
- // property cache is updated before the callbacks are invoked.
- invokeSignalCallbacks(signalName, signals[signalName]);
- }
- }
-
- this.signalEmitted = function(signalName, signalArgs)
- {
- invokeSignalCallbacks(signalName, signalArgs);
- }
-
- function addMethod(methodData)
- {
- var methodName = methodData[0];
- var methodIdx = methodData[1];
- object[methodName] = function() {
- var args = [];
- var callback;
- for (var i = 0; i < arguments.length; ++i) {
- if (typeof arguments[i] === "function")
- callback = arguments[i];
- else
- args.push(arguments[i]);
- }
-
- webChannel.exec({
- "type": QWebChannelMessageTypes.invokeMethod,
- "object": object.__id__,
- "method": methodIdx,
- "args": args
- }, function(response) {
- if (response !== undefined) {
- var result = object.unwrapQObject(response);
- if (callback) {
- (callback)(result);
- }
- }
- });
- };
- }
-
- function bindGetterSetter(propertyInfo)
- {
- var propertyIndex = propertyInfo[0];
- var propertyName = propertyInfo[1];
- var notifySignalData = propertyInfo[2];
- // initialize property cache with current value
- // NOTE: if this is an object, it is not directly unwrapped as it might
- // reference other QObject that we do not know yet
- object.__propertyCache__[propertyIndex] = propertyInfo[3];
-
- if (notifySignalData) {
- if (notifySignalData[0] === 1) {
- // signal name is optimized away, reconstruct the actual name
- notifySignalData[0] = propertyName + "Changed";
- }
- addSignal(notifySignalData, true);
- }
-
- Object.defineProperty(object, propertyName, {
- configurable: true,
- get: function () {
- var propertyValue = object.__propertyCache__[propertyIndex];
- if (propertyValue === undefined) {
- // This shouldn't happen
- console.warn("Undefined value in property cache for property \"" + propertyName + "\" in object " + object.__id__);
- }
-
- return propertyValue;
- },
- set: function(value) {
- if (value === undefined) {
- console.warn("Property setter for " + propertyName + " called with undefined value!");
- return;
- }
- object.__propertyCache__[propertyIndex] = value;
- webChannel.exec({
- "type": QWebChannelMessageTypes.setProperty,
- "object": object.__id__,
- "property": propertyIndex,
- "value": value
- });
- }
- });
-
- }
-
- // ----------------------------------------------------------------------
-
- data.methods.forEach(addMethod);
-
- data.properties.forEach(bindGetterSetter);
-
- data.signals.forEach(function(signal) { addSignal(signal, false); });
-
- for (var name in data.enums) {
- object[name] = data.enums[name];
- }
- }
-
- //required for use with nodejs
- if (typeof module === 'object') {
- module.exports = {
- QWebChannel: QWebChannel
- };
- }
js调用py文件(js_call_py.html)
- <html>
- <head>
- <title>A Demo Page</title>
- <meta charset="UTF-8">
- <script src="./qwebchannel.js"></script>
- <script language="javascript">
-
- function callback(result) {
- alert('计算结果:' + result)
- }
-
- document.addEventListener("DOMContentLoaded", function () {
-
- new QWebChannel( qt.webChannelTransport, function(channel) {
-
- window.obj = channel.objects.obj;
- });
- });
-
- function onFactorial() {
-
- if ( window.obj) {
-
- var n = parseInt(document.getElementById('n').value);
- window.obj.factorial(n,callback)
-
- }
-
- }
-
-
- </script>
- </head>
-
- <body>
- <form>
- <label >请输入N:</label>
- <input type="text" id="n"></input>
- <br />
- <input type="button" value="计算阶乘" onclick="onFactorial()">
-
- </form>
- </body>
- </html>
阶乘功能类(factorial.py)
- from PyQt5.QtCore import *
-
-
- class Factorial(QObject):
- @pyqtSlot(int, result=int)
- def factorial(self,n):
- if n == 0 or n == 1:
- return 1
- else:
- return self.factorial(n - 1) * n
调用类(PyFactorial.py)
- from PyQt5.QtWebChannel import QWebChannel
- from PyQt5.QtCore import *
- from PyQt5.QtWidgets import *
- from PyQt5.QtWebEngineWidgets import *
- import sys
- import os
- from factorial import *
-
- channel = QWebChannel()
- factorial = Factorial()
- class PyFactorial(QWidget):
-
- def __init__(self):
- super(PyFactorial, self).__init__()
- self.setWindowTitle('Python计算阶乘')
- self.resize(600,300)
- layout=QVBoxLayout()
-
- self.browser = QWebEngineView()
- url = os.getcwd() + '/js_call_py.html'
- #装载本地html文件
- self.browser.load(QUrl.fromLocalFile(url))
- channel.registerObject("obj",factorial)
- self.browser.page().setWebChannel(channel)
-
- layout.addWidget(self.browser)
- self.setLayout(layout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- win = PyFactorial()
- win.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 14:29
- import sys, math
- from PyQt5.QtWidgets import *
-
-
- class AbsoluteLayout(QWidget):
- def __init__(self):
- super(AbsoluteLayout, self).__init__()
- self.setWindowTitle('绝对布局')
- self.resize(300, 200)
-
- self.label1 = QLabel('欢迎', self)
- self.label1.move(15, 20)
-
- self.label2 = QLabel('学习', self)
- self.label2.move(35, 40)
-
- self.label3 = QLabel('PyQt5', self)
- self.label3.move(55, 60)
-
- self.label4 = QLabel('JavaEE', self)
- self.label4.move(75, 80)
-
- self.label5 = QLabel('Uniapp', self)
- self.label5.move(95, 100)
-
- self.label6 = QLabel('大数据', self)
- self.label6.move(115, 120)
-
- self.label2 = QLabel('区块链', self)
- self.label2.move(135, 140)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = AbsoluteLayout()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 14:34
- import sys, math
- from PyQt5.QtWidgets import *
-
-
- class HBoxLayout(QWidget):
- def __init__(self):
- super(HBoxLayout, self).__init__()
- self.setWindowTitle('水平盒布局')
- self.resize(300, 200)
-
- hlayout = QHBoxLayout()
- hlayout.addWidget(QPushButton('JavaEE'))
- hlayout.addWidget(QPushButton('Uniapp'))
- hlayout.addWidget(QPushButton('大数据'))
- hlayout.addWidget(QPushButton('区块链'))
- hlayout.addWidget(QPushButton('人工智能'))
- # 设置控件之间的间距
- hlayout.setSpacing(20)
-
- self.setLayout(hlayout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = HBoxLayout()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 14:37
- import sys, math
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
-
-
- class HBoxLayout(QWidget):
- def __init__(self):
- super(HBoxLayout, self).__init__()
- self.setWindowTitle('水平盒布局')
- self.resize(300, 200)
-
- hlayout = QHBoxLayout()
- '''
- 参数二:拉伸量(几个单位),eg:按钮1后面有2个单位的拉伸,按钮2后面有4个单位的拉伸
- 参数三:对齐方式,eg:按钮1是按照左上方对齐,其他以此类推
- '''
- hlayout.addWidget(QPushButton('按钮1'), 2, Qt.AlignLeft | Qt.AlignTop)
- hlayout.addWidget(QPushButton('按钮2'), 4, Qt.AlignLeft | Qt.AlignTop)
- hlayout.addWidget(QPushButton('按钮3'), 1, Qt.AlignLeft | Qt.AlignTop)
- hlayout.addWidget(QPushButton('按钮4'), 1, Qt.AlignLeft | Qt.AlignBottom)
- hlayout.addWidget(QPushButton('按钮5'), 1, Qt.AlignLeft | Qt.AlignBottom)
- # 设置控件之间的间距
- hlayout.setSpacing(40)
-
- self.setLayout(hlayout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = HBoxLayout()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 14:42
- import sys, math
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
-
-
- class VBoxLayout(QWidget):
- def __init__(self):
- super(VBoxLayout, self).__init__()
- self.setWindowTitle('垂直盒布局')
- self.resize(300, 200)
-
- hlayout = QVBoxLayout()
-
- hlayout.addWidget(QPushButton('JavaEE'))
- hlayout.addWidget(QPushButton('Uniapp'))
- hlayout.addWidget(QPushButton('大数据'))
- hlayout.addWidget(QPushButton('区块链'))
- hlayout.addWidget(QPushButton('人工智能'))
- # 设置控件之间的间距
- hlayout.setSpacing(40)
-
- self.setLayout(hlayout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = VBoxLayout()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 14:45
- import sys, math
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
-
-
- class Stretch(QWidget):
- def __init__(self):
- super(Stretch, self).__init__()
- self.setWindowTitle('设置伸缩量')
- self.resize(800, 100)
-
- btn1 = QPushButton(self)
- btn2 = QPushButton(self)
- btn3 = QPushButton(self)
- btn1.setText('JavaEE')
- btn2.setText('Uniapp')
- btn3.setText('大数据')
-
- layout = QHBoxLayout()
- # 伸缩量,在水平布局里有讲过
- layout.addStretch(1) # 在按钮前面添加伸缩单位
- layout.addWidget(btn1)
-
- layout.addStretch(2)
- layout.addWidget(btn2)
-
- layout.addStretch(3)
- layout.addWidget(btn3)
-
- self.setLayout(layout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = Stretch()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 14:47
- import sys, math
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
-
-
- class Stretch(QWidget):
- def __init__(self):
- super(Stretch, self).__init__()
- self.setWindowTitle('设置伸缩量')
- self.resize(1000, 100)
-
- btn1 = QPushButton(self)
- btn2 = QPushButton(self)
- btn3 = QPushButton(self)
- btn4 = QPushButton(self)
- btn5 = QPushButton(self)
- btn1.setText('JavaEE')
- btn2.setText('Uniapp')
- btn3.setText('大数据')
- btn4.setText('区块链')
- btn5.setText('人工智能')
-
- layout = QHBoxLayout()
-
- layout.addStretch(0) # 伸缩量设置为0,是先排列
- layout.addWidget(btn1)
- layout.addWidget(btn2)
- layout.addWidget(btn3)
- layout.addWidget(btn4)
- layout.addWidget(btn5)
-
- btnOK = QPushButton(self)
- btnOK.setText('确定')
- btnCancel = QPushButton(self)
- btnCancel.setText('取消')
- layout.addStretch(1)
-
- layout.addWidget(btnOK)
- layout.addWidget(btnCancel)
-
- self.setLayout(layout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = Stretch()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 14:50
- import sys, math
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
-
-
- class RBBtn(QWidget):
- def __init__(self):
- super(RBBtn, self).__init__()
- self.setWindowTitle('让按钮永远在右下角')
- self.resize(400, 300)
-
- okBtn = QPushButton('确定')
- cancelBtn = QPushButton('取消')
-
- hbox = QHBoxLayout()
- hbox.addStretch(1)
- hbox.addWidget(okBtn)
- hbox.addWidget(cancelBtn)
-
- vbox = QVBoxLayout()
- btn1 = QPushButton('按钮1')
- btn2 = QPushButton('按钮2')
- btn3 = QPushButton('按钮3')
-
- vbox.addStretch(0)
- vbox.addWidget(btn1)
- vbox.addWidget(btn2)
- vbox.addWidget(btn3)
- vbox.addStretch(1)
-
- # 布局之间的叠加,用addLayout
- vbox.addLayout(hbox)
-
- self.setLayout(vbox)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = RBBtn()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 14:57
- import sys, math
- from PyQt5.QtWidgets import *
-
-
- class Calc(QWidget):
- def __init__(self):
- super(Calc, self).__init__()
- self.setWindowTitle('栅格布局:用循环方式实现计算器UI')
-
- 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)]
- print(positions)#输出 按钮名称和坐标文职
-
- # 在元组前面加星号可将元组变成两个单个的值
- print(*(1, 2)) # 输出的不是元组,而是两个值
- # zip函数返回一个可迭代的对象,接受多个可迭代的序列,将相应的元素组合成一对元组
- for position, name in zip(positions, names):
- if name == '':
- continue
- # print(position)
- # print(name)
- btn = QPushButton(name)
- grid.addWidget(btn, *position)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = Calc()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 15:09
- import sys, math
- from PyQt5.QtWidgets import *
-
-
- class GridForm(QWidget):
- def __init__(self):
- super(GridForm, self).__init__()
- self.setWindowTitle('栅格布局:进行表单UI设计')
- # 标签
- titleLabel = QLabel('标题')
- authorLabel = QLabel('作者')
- contentLabel = QLabel('内容')
- # 单行输入
- titleEdit = QLineEdit()
- authorEdit = QLineEdit()
- # 多行输入
- contentEdit = QTextEdit()
-
- grid = QGridLayout()
- # 控件间距
- grid.setSpacing(10)
- grid.addWidget(titleLabel, 1, 0) # 位置两个轴都是从0开始,这里没用而已
- grid.addWidget(titleEdit, 1, 1)
-
- grid.addWidget(authorLabel, 2, 0)
- grid.addWidget(authorEdit, 2, 1)
-
- grid.addWidget(contentLabel, 3, 0)
- grid.addWidget(contentEdit, 3, 1, 5, 1) # 空间上占五行一列
-
- self.setLayout(grid)
- self.resize(400, 300)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = GridForm()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 15:15
- import sys, math
- from PyQt5.QtWidgets import *
-
-
- class FormLayout(QWidget):
- def __init__(self):
- super(FormLayout, self).__init__()
- self.setWindowTitle('表单布局')
- self.resize(350, 300)
- # 标签
- titleLabel = QLabel('标题')
- authorLabel = QLabel('作者')
- contentLabel = QLabel('内容')
- # 单行输入
- titleEdit = QLineEdit()
- authorEdit = QLineEdit()
- # 多行输入
- contentEdit = QTextEdit()
-
- formLayout = QFormLayout()
- formLayout.addRow(titleLabel, titleEdit)
- formLayout.addRow(authorLabel, authorEdit)
- formLayout.addRow(contentLabel, contentEdit)
-
- self.setLayout(formLayout)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = FormLayout()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 15:16
- import sys, math
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import Qt
-
-
- class Splitter(QWidget):
- def __init__(self):
- super(Splitter, self).__init__()
- self.setWindowTitle('Splitter例子')
- self.setGeometry(400, 300, 300, 200)
-
- topLeft = QFrame()
- topLeft.setFrameShape(QFrame.StyledPanel) # 面板类型
-
- bottom = QFrame()
- bottom.setFrameShape(QFrame.StyledPanel)
-
- splitter1 = QSplitter(Qt.Horizontal) # 水平拖动
- textEdit = QTextEdit()
- splitter1.addWidget(topLeft)
- splitter1.addWidget(textEdit)
- # 设置里面的控件的初始尺寸,eg:topLeft占100,textEdit占200
- splitter1.setSizes([100, 200])
-
- splitter2 = QSplitter(Qt.Vertical) # 垂直拖动
- splitter2.addWidget(splitter1)
- splitter2.addWidget(bottom)
-
- hbox = QHBoxLayout()
- hbox.addWidget(splitter2)
- self.setLayout(hbox)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = Splitter()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 15:24
- import sys, math
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
-
-
- class Demo(QWidget):
- def __init__(self):
- super(Demo, self).__init__()
- self.initUI()
-
- def initUI(self):
- self.setGeometry(300, 300, 300, 100)
- self.setWindowTitle('信号(Signal)与槽(Slot)')
- self.btn = QPushButton('我的按钮', self)
- self.btn.clicked.connect(self.onClick)
-
- def onClick(self):
- self.btn.setText('信号已经发出')
- self.btn.setStyleSheet('QPushButton(max-width:500px;min-width:500px)')
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = Demo()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 15:30
- import sys, math
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
-
-
- class MyTypeSignal(QObject):
- # 定义一个信号
- sendmsg = pyqtSignal(object)
-
- # 调用run来实现触发
- def run(self):
- self.sendmsg.emit('Hello PyQt5') # 给槽传递一个参数
-
-
- class MySlot(QObject):
- # 槽函数
- def get(self, msg):
- print('信息:' + msg)
-
-
- if __name__ == '__main__':
- send = MyTypeSignal()
- slot = MySlot()
- send.sendmsg.connect(slot.get) # 连接信号与槽函数
- send.run() # 发送信号
- # 断开信号与槽的连接
- # send.sendmsg.disconnect(slot.get)
-
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 15:38
- import sys, math
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
-
-
- class MyTypeSignal(QObject):
- # 定义一个信号
- sendmsg = pyqtSignal(object)
- # 发送三个参数的信号
- sendmsg1 = pyqtSignal(str, int, int)
-
- # 调用run来实现触发
- def run(self):
- self.sendmsg.emit('Hello PyQt5') # 给槽传递一个参数
-
- def run1(self):
- self.sendmsg1.emit('hello', 3, 4)
-
-
- class MySlot(QObject):
- # 槽函数
- def get(self, msg):
- print('信息:' + msg)
-
- def get1(self, msg, a, b):
- print(msg)
- print(a + b)
-
-
- if __name__ == '__main__':
- send = MyTypeSignal()
- slot = MySlot()
-
- send.sendmsg.connect(slot.get) # 连接信号与槽函数
- send.sendmsg1.connect(slot.get1)
-
- send.run() # 发送信号
- send.run1() # 别忘了调用相应的触发函数!!!!
-
- # 断开信号与槽的连接
- # send.sendmsg.disconnect(slot.get)
-
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 15:43
- import sys, math
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
-
-
- class MultiSignal(QObject):
- # 无参数
- signal1 = pyqtSignal()
- # 有一个整型的参数
- signal2 = pyqtSignal(int)
- # 参数一是整型,参数二是字符型
- signal3 = pyqtSignal(int, str)
- # 参数是一个列表
- signal4 = pyqtSignal(list)
- # 参数是一个字典
- signal5 = pyqtSignal(dict)
- # 声明一个重载版本的信号,中括号之间是或的意思,也就是槽函数可以是两个参数:int和str类型,也可以是一个参数:str类型
- signal6 = pyqtSignal([int, str], [str])
-
- def __init__(self):
- super(MultiSignal, self).__init__()
- self.signal1.connect(self.signalcall1)
- self.signal2.connect(self.signalcall2)
- self.signal3.connect(self.signalcall3)
- self.signal4.connect(self.signalcall4)
- self.signal5.connect(self.signalcall5)
- # self.signal6.connect(self.signalcall6)#默认关联到重构的第一个槽函数上
- # 为了可读性,可像下面那样写
- self.signal6[str].connect(self.signalcall6Overload)
- self.signal6[int, str].connect(self.signalcall6)
-
- self.signal1.emit()
- self.signal2.emit(10)
- self.signal3.emit(1, 'hello world')
- self.signal4.emit([1, 2, 3, 4, 5])
- self.signal5.emit({'name': 'Bill', 'age': 30})
- self.signal6[str].emit('test')
- self.signal6[int, str].emit(20, 'mytest')
-
- # 槽函数
- def signalcall1(self):
- print('signal1 emit')
-
- def signalcall2(self, val):
- print('signa2 emit,value:', val)
-
- def signalcall3(self, val, text):
- print('signa3 emit,value:', val, text)
-
- def signalcall4(self, val):
- print('signa4 emit,value:', val)
-
- def signalcall5(self, val):
- print('signa5 emit,value:', val)
-
- def signalcall6(self, val, text):
- print('signa6 emit,value:', val, text)
-
- def signalcall6Overload(self, val):
- print('signa6 overload emit,value:', val)
-
-
- if __name__ == '__main__':
- multiSignal = MultiSignal()
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 15:54
- import sys, math
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
-
-
- class NNSignal(QObject):
- signal1 = pyqtSignal() # 无参数
- signal2 = pyqtSignal(int)
- signal3 = pyqtSignal()
-
- def __init__(self):
- super(NNSignal, self).__init__()
- # 一个信号对应多个槽
- self.signal1.connect(self.call1)
- self.signal1.connect(self.call11)
-
- self.signal1.emit()
- # 信号绑定到槽上
- self.signal2.connect(self.signal1)
- print('*****************************')
- self.signal2.emit(2) # 触发了信号1
- '''
- 以上操作的运行结果
- call1 emit
- call11 emit
- call1 emit
- call11 emit
- '''
- print('************************************')
- # 解绑
- self.signal1.disconnect(self.call1)
- self.signal1.disconnect(self.call11)
- self.signal2.disconnect(self.signal1)
- # 重新绑定
- self.signal1.connect(self.call1)
- self.signal2.connect(self.call2)
- # 一个槽函数绑定到多个信号上
- self.signal3.connect(self.call1)
-
- self.signal1.emit()
- self.signal2.emit(100)
- self.signal3.emit()
-
- def call1(self):
- print('call1 emit')
-
- def call11(self):
- print('call11 emit')
-
- def call2(self, val):
- print('call2 emit', val)
-
-
- if __name__ == '__main__':
- nnSignal = NNSignal()
本质就是为一个类添加信号,只不过这个类是窗口类
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 16:02
- import sys, math
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
-
-
- class WinSignal(QWidget):
- # 定义一个信号
- btn_clicked_signal = pyqtSignal()
-
- def __init__(self):
- super(WinSignal, self).__init__()
- self.setWindowTitle('为窗口添加信号')
- self.resize(300, 100)
-
- btn = QPushButton('关闭窗口', self)
- btn.clicked.connect(self.btn_clicked)
- self.btn_clicked_signal.connect(self.btn_close)
-
- # 起触发函数作用的槽函数
- def btn_clicked(self):
- self.btn_clicked_signal.emit()
-
- # 关闭窗口作用的槽函数
- def btn_close(self):
- self.close()
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = WinSignal()
- main.show()
- sys.exit(app.exec_())
多线程更新UI数据,两个线程中传递数据
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 16:09
- import sys, math
- import time
- from PyQt5.QtWidgets import QApplication, QDialog, QLineEdit
- from PyQt5.QtCore import QThread, pyqtSignal, QDateTime
-
-
- class BackendThread(QThread):
- # 更新日期的信号
- update_date = pyqtSignal(str)
-
- def run(self):
- while True:
- date = QDateTime.currentDateTime()
- currentTime = date.toString('yyyy-MM-dd hh:mm:ss')
- # 信号参数是当前时间
- self.update_date.emit(str(currentTime))
- time.sleep(1) # 隔1s就发送一次信号
-
-
- class ThreadUpdateUI(QDialog):
- def __init__(self):
- QDialog.__init__(self)
- self.setWindowTitle('多线程更新UI数据')
- self.resize(400, 100)
- # 存放当前时间
- self.input = QLineEdit(self)
- self.input.resize(400, 100)
- self.initUI()
-
- def initUI(self):
- self.backend = BackendThread()
- self.backend.update_date.connect(self.handleDisplay)
- self.backend.start() # 开启线程,自动调用run
-
- # 槽函数是主线程
- def handleDisplay(self, data): # data是当前时间
- self.input.setText(data)
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = ThreadUpdateUI()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 16:22
- from PyQt5 import QtCore
- from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton
- import sys
-
-
- class AutoSignalSlot(QWidget):
- def __init__(self):
- super(AutoSignalSlot, self).__init__()
- self.resize(300, 100)
-
- self.okBtn = QPushButton('ok', self)
- self.okBtn1 = QPushButton('cancel', self)
- # 设置自动连接
- self.okBtn.setObjectName('okBtn')
- self.okBtn1.setObjectName('cancelBtn')
- QtCore.QMetaObject.connectSlotsByName(self)
-
- layout = QHBoxLayout()
- layout.addWidget(self.okBtn)
- layout.addWidget(self.okBtn1)
- self.setLayout(layout)
- # 传统连接信号与槽
- # self.okBtn.clicked.connect(self.on_okBtn_clicked)
-
- # 命名规则:on_发送者对象(objectname)名称_发射信号名称(self,参数)
- @QtCore.pyqtSlot() # 标注为槽函数,以供自动连接使用
- def on_okBtn_clicked(self):
- print('点击了ok按钮')
-
- @QtCore.pyqtSlot()
- def on_cancelBtn_clicked(self):
- print('点击了cancel按钮')
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = AutoSignalSlot()
- main.show()
- sys.exit(app.exec_())
Lambda表达式:匿名函数,也就是没有名字的函数。
将Lambda赋给一个变量,这个变量就成为了一个函数引用。或者将Lambda表达式作为一个参数传入函数。
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 16:32
- # Lambda表达式示例
- fun = lambda: print('hello world')
- fun()
-
- fun = lambda x, y: print(x, y)
- fun('a', 'b')
-
- from PyQt5.QtWidgets import *
- import sys
-
-
- class LambdaSlotArg(QMainWindow):
- def __init__(self):
- super(LambdaSlotArg, self).__init__()
- self.setWindowTitle('用Lambda表达式为槽函数传递参数')
-
- btn1 = QPushButton('按钮1')
- btn2 = QPushButton('按钮2')
-
- ok = 200
- btn1.clicked.connect(lambda: self.onButtonClick(10, ok))
- btn2.clicked.connect(lambda: self.onButtonClick(ok, -20))
- btn1.clicked.connect(lambda: QMessageBox.information(self, '结果', '单击了btn1'))
-
- layout = QHBoxLayout()
- layout.addWidget(btn1)
- layout.addWidget(btn2)
-
- mainFrame = QWidget()
- mainFrame.setLayout(layout)
- self.setCentralWidget(mainFrame)
-
- def onButtonClick(self, m, n):
- print('m+n=', m + n)
- QMessageBox.information(self, '结果', str(m + n))
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = LambdaSlotArg()
- main.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 16:43
- from PyQt5.QtWidgets import *
- from functools import partial
- import sys
-
-
- class PartialSlotArg(QMainWindow):
- def __init__(self):
- super(PartialSlotArg, self).__init__()
- self.setWindowTitle('用partial对象为槽函数传递参数')
-
- btn1 = QPushButton('按钮1')
- btn2 = QPushButton('按钮2')
-
- x = 20
- y = -123
- btn1.clicked.connect(partial(self.onButtonClick, 10, 20))
- btn2.clicked.connect(partial(self.onButtonClick, x, y))
-
- layout = QHBoxLayout()
- layout.addWidget(btn1)
- layout.addWidget(btn2)
-
- mainFrame = QWidget()
- mainFrame.setLayout(layout)
- self.setCentralWidget(mainFrame)
-
- def onButtonClick(self, m, n):
- print('m+n=', m + n)
- QMessageBox.information(self, '结果', str(m + n))
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = PartialSlotArg()
- main.show()
- sys.exit(app.exec_())
系统已经定义了很多槽函数,我们能可以覆盖重写这些槽函数
我们通过覆盖keyPressEvent槽函数修改了按ESC和ALT键的行为。当我们按ESC的时候,窗口关闭,当按ALT键的时候窗口标题修改为"按下了Alt键"。
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 16:49
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
- import sys
-
-
- class OverrideSlot(QWidget):
- def __init__(self):
- super().__init__()
- self.setWindowTitle('override(覆盖)槽函数')
-
- # 键盘按下的槽函数,不需要连接,系统已经给连接了
- def keyPressEvent(self, e):
- # 如果按下Esc键,则关闭窗口
- if e.key() == Qt.Key_Escape:
- self.close()
- # 如果按下Alt键,修改窗口标题为 按下Alt键
- elif e.key() == Qt.Key_Alt:
- self.setWindowTitle('按下Alt键')
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- main = OverrideSlot()
- main.show()
- sys.exit(app.exec_())
所谓的交互就是数据的传递。不使用信号与槽就是强耦合的方式,即两个窗口之间相互调用控件。
DateDialog.py
# @CSDN王家视频教程图书馆 # @Time 2022/11/24 16:55 from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class DateDialog(QDialog): def __init__(self, parent=None): super(DateDialog, self).__init__(parent) # 当这里面传入self,相当于 self.setLayout(layout),而且上面的parent必须有 layout = QVBoxLayout(self) ''' QDateTimeEdit是一个允许用户编辑日期时间的控件,可以使用键盘上的上下键头按钮来增加或减少日期的时间值, QDateTimeEdit通过setDisplayFormat()函数来设置显示的日期时间格式 ''' # 日期时间输入框 self.datetime = QDateTimeEdit(self) # print(isinstance(datetime,DateDialog)) # popup (n.) 弹出;弹跳装置;发射 self.datetime.setCalendarPopup(True) # 显示当前日期 self.datetime.setDateTime(QDateTime.currentDateTime()) layout.addWidget(self.datetime) # 两个按钮 buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) # 下面两个槽函数是系统已经定义好的 buttons.accepted.connect(self.accept) # reject (v.)拒绝 buttons.rejected.connect(self.reject) layout.addWidget(buttons) def dateTime(self): # 返回当前日期 return self.datetime.dateTime() @staticmethod # 静态方法 def getDateTime(parent=None): dialog = DateDialog(parent) # 显示对话框 result = dialog.exec_() date = dialog.dateTime() # print('date.date():',date.date()) #日期:年月日 # print('date.time():',date.time())#时间:时分秒 # 第三个参数是:是否点击了ok return (date.date(), date.time(), result == QDialog.Accepted)
MutilWindow1.py
# @CSDN王家视频教程图书馆 # @Time 2022/11/24 16:57 import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * from DateDialog import DateDialog class MutilWindow1(QWidget): def __init__(self): super(MutilWindow1, self).__init__() self.setWindowTitle('多窗口交互(1):不使用信号与槽') # 单行输入 self.lineEdit = QLineEdit(self) self.btn1 = QPushButton('弹出对话框1') self.btn1.clicked.connect(self.onButton1Click) self.btn2 = QPushButton('弹出对话框2') self.btn2.clicked.connect(self.onButton2Click) # 栅格布局 gridLayout = QGridLayout() gridLayout.addWidget(self.lineEdit) gridLayout.addWidget(self.btn1) gridLayout.addWidget(self.btn2) self.setLayout(gridLayout) def onButton1Click(self): dialog = DateDialog(self) result = dialog.exec_() date = dialog.dateTime() self.lineEdit.setText(date.date().toString()) # 销毁窗口 dialog.destroy() def onButton2Click(self): date, time, result = DateDialog.getDateTime() self.lineEdit.setText(date.toString()) if result == QDialog.Accepted: print('点击确定按钮') else: print('点击取消按钮') if __name__ == '__main__': app = QApplication(sys.argv) main = MutilWindow1() main.show() sys.exit(app.exec_())
低耦合:
如果一个窗口A与另一个窗口B交互,那么A尽量不要直接访问B窗口中的控件,
应该在窗口A中访问B窗口中的信号,并指定与信号绑定的槽函数例:如果A直接访问B窗口的控件,一旦B窗口控件发生改变,那么A和B的代码都需要变化
如果A访问的是B中的信号,那么B中的控件发生了改变,只需要修改B中的代码即可。信号就是为此而生
NewDateDialog.py
# @CSDN王家视频教程图书馆 # @Time 2022/11/24 17:40 from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class NewDateDialog(QDialog): # 定义一个信号,有一个字符串型的参数 Signal_OneParameter = pyqtSignal(str) def __init__(self, parent=None): super(NewDateDialog, self).__init__(parent) self.setWindowTitle('子窗口:用来发射信号') # 在布局中添加部件,垂直布局 layout = QVBoxLayout(self) self.label = QLabel(self) self.label.setText('前者发射内置信号\n后者发射自定义信号') # 定义两个日期时间编辑框 self.datetime_inner = QDateTimeEdit(self) # 弹出模式 self.datetime_inner.setCalendarPopup(True) # 设置为当前时间 self.datetime_inner.setDateTime(QDateTime.currentDateTime()) self.datetime_emit = QDateTimeEdit(self) self.datetime_emit.setCalendarPopup(True) self.datetime_emit.setDateTime(QDateTime.currentDateTime()) # 放入垂直布局 layout.addWidget(self.label) layout.addWidget(self.datetime_inner) layout.addWidget(self.datetime_emit) # 使用两个button(ok和cancel)分别连接accept()和reject()槽函数 buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) layout.addWidget(buttons) self.datetime_emit.dateTimeChanged.connect(self.emit_signal) def emit_signal(self): date_str = self.datetime_emit.dateTime().toString() print(date_str) # 发出信号 self.Signal_OneParameter.emit(date_str)
MutilWindow2.py
# @CSDN王家视频教程图书馆 # @Time 2022/11/24 17:40 import sys from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * from NewDateDialog import NewDateDialog class MultiWindow2(QWidget): def __init__(self, parent=None): super(MultiWindow2, self).__init__(parent) self.resize(400, 90) self.setWindowTitle('多窗口交互(2):使用信号与槽') self.open_btn = QPushButton('获取时间') self.lineEdit_inner = QLineEdit(self) self.lineEdit_emit = QLineEdit(self) self.open_btn.clicked.connect(self.openDialog) self.lineEdit_inner.setText('接收子窗口内置信号的时间') self.lineEdit_emit.setText('接收子窗口自定义信号的时间') grid = QGridLayout() grid.addWidget(self.lineEdit_inner) grid.addWidget(self.lineEdit_emit) grid.addWidget(self.open_btn) self.setLayout(grid) def openDialog(self): dialog = NewDateDialog(self) # dateTimeChanged 是时间改变信号,即手动使日期时间发生改变就会发出信号 # 连接子窗口的内置信号与主窗口的槽函数 dialog.datetime_inner.dateTimeChanged.connect(self.deal_inner_slot) # 连接子窗口的自定义信号与主窗口的槽函数(推荐用这种) dialog.Signal_OneParameter.connect(self.deal_emit_slot) dialog.show() def deal_inner_slot(self, date): self.lineEdit_inner.setText(date.toString()) def deal_emit_slot(self, dateStr): self.lineEdit_emit.setText(dateStr) if __name__ == "__main__": app = QApplication(sys.argv) form = MultiWindow2() form.show() sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 18:13
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5 import QtCore
-
- # 窗口可以显示的风格样式
- print('窗口可以显示的风格样式:', QStyleFactory.keys())
-
-
- class WindowStyle(QWidget):
- def __init__(self):
- super().__init__()
- self.setWindowTitle('设置窗口风格')
- horizontalLayout = QHBoxLayout()
- self.styleLabel = QLabel('设置窗口风格:')
- # 下拉框
- self.styleComboBox = QComboBox()
- self.styleComboBox.addItems(QStyleFactory.keys())
-
- # 获取当前窗口的风格
- print('当前窗口的风格:', QApplication.style().objectName())
- # 获取当前窗口的风格的索引
- index = self.styleComboBox.findText(QApplication.style().objectName(), QtCore.Qt.MatchFixedString)
- # 将下拉框初始设置为当前窗口的风格的名字
- self.styleComboBox.setCurrentIndex(index)
-
- self.styleComboBox.activated[str].connect(self.handleStyleChanged)
-
- horizontalLayout.addWidget(self.styleLabel)
- horizontalLayout.addWidget(self.styleComboBox)
- self.setLayout(horizontalLayout)
-
- def handleStyleChanged(self, style):
- # 设置风格
- QApplication.setStyle(style)
-
-
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- form = WindowStyle()
- form.show()
- sys.exit(app.exec_())
setWindowFlags ( WindowFlags type )
FrameWindowHint 没有边框的窗口
WindowStaysOnTopHint 总在最上面的窗口
CustomizeWindowHint 自定义窗口标题栏,以下标志必须与这个标志一起使用才有效,否则窗口将有默认的标题栏
WindowTitleHint 显示窗口标题栏
WindowSystemMenuHint 显示系统菜单
WindowMinimizeButtonHint 显示最小化按钮
WindowMaximizeButtonHint 显示最大化按钮
WindowMinMaxButtonsHint 显示最小化按钮和最大化按钮
WindowCloseButtonHint 显示关闭按钮
setWindowFlags(FramelessWindowHint) 直接隐藏掉
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 18:43
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
-
-
- ### 自定义窗口类
- class WindowMaxMin(QWidget):
- # 构造函数
- def __init__(self, parent=None):
- '''构造函数'''
- # 调用父类构造函数
- super(WindowMaxMin, self).__init__(parent)
- self.resize(300, 400)
- self.setWindowTitle("用代码控制窗口的最大化和最小化")
- self.setWindowFlags(Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint | Qt.WindowMinMaxButtonsHint)
-
- layout = QVBoxLayout()
- maxButton1 = QPushButton()
- maxButton1.setText('窗口最大化1 使用自己的方法')
- maxButton1.clicked.connect(self.maximized1)
-
- maxButton2 = QPushButton()
- maxButton2.setText('窗口最大化2 使用系统提供的方法')
- maxButton2.clicked.connect(self.showMaximized)
-
- minButton = QPushButton()
- minButton.setText('窗口最小化')
- minButton.clicked.connect(self.showMinimized)
-
- layout.addWidget(maxButton1)
- layout.addWidget(maxButton2)
- layout.addWidget(minButton)
- self.setLayout(layout)
-
- def maximized1(self):
- # 获得桌面
- desktop = QApplication.desktop()
- # 获取桌面可用尺寸
- rect = desktop.availableGeometry()
- self.setGeometry(rect)
-
-
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- window = WindowMaxMin()
- window.show()
- # 应用程序事件循环
- sys.exit(app.exec_())
需要解决3个核心内容
1. 如何绘图在paintEvent方法中绘图,通过调用update方法触发painEvent的调用
2. 在哪里绘图
在白色背景的QPixmap对象中绘图
3. 如何通过移动鼠标进行绘图
鼠标拥有3个事件:
(1)鼠标按下:mousePressEvent
(2)鼠标移动:mouseMoveEvent
(3)鼠标抬起:mouseReleaseEvent
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 18:57
- import sys
- from PyQt5.QtWidgets import QApplication, QWidget
- from PyQt5.QtGui import QPainter, QPixmap
- from PyQt5.QtCore import Qt, QPoint
-
-
- class Drawing(QWidget):
- def __init__(self, parent=None):
- super(Drawing, self).__init__(parent)
- self.setWindowTitle("绘图应用")
- self.pix = QPixmap()
- self.lastPoint = QPoint()
- self.endPoint = QPoint()
- self.initUi()
-
- def initUi(self):
-
- self.resize(600, 600)
- '''
- QPixmap 类用于绘图设备的图像显示,可作为一个 QPaintDevice 对象,也可以加载到一个控件中。
- QPixmap 可以读取的图像文件类型有:BMP、GIF、JPG、JPEG、PNG、PBM、PGM、PPM、XBM、XPM 等。
- '''
- # 画布大小为600*600,背景为白色
- self.pix = QPixmap(600, 600)
- self.pix.fill(Qt.white)
-
- # 下面的方法都是自动调用的
- def paintEvent(self, event):
- # 画笔
- pp = QPainter(self.pix)
- # 根据鼠标指针前后两个位置绘制直线
- pp.drawLine(self.lastPoint, self.endPoint)
- # 让前一个坐标值等于后一个坐标值,
- # 这样就能实现画出连续的线
- self.lastPoint = self.endPoint
- painter = QPainter(self)
- # pixmap (n.)像素映射,象图
- # 即先画在QPixmap上,再从图像文件中提取 Pixmap 并将其显示在指定位置
- painter.drawPixmap(0, 0, self.pix)
-
- # 鼠标按下
- def mousePressEvent(self, event):
- # 如果鼠标左键按下
- if event.button() == Qt.LeftButton:
- # 获得当前坐标
- self.lastPoint = event.pos()
-
- # 鼠标移动
- def mouseMoveEvent(self, event):
- # 如果鼠标左键一直按着
- if event.buttons() and Qt.LeftButton:
- self.endPoint = event.pos()
- self.update() # 触发paintEvent
-
- # 鼠标抬起
- def mouseReleaseEvent(self, event):
- # 鼠标左键释放
- if event.button() == Qt.LeftButton:
- self.endPoint = event.pos()
- # 进行重新绘制
- self.update() # 每次调用paintEvent都会重新触发一次
-
-
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- form = Drawing()
- form.show()
- sys.exit(app.exec_())
-
QSS (Qt Style Sheets)
Qt样式表
用于设置控件的样式
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 19:37
- from PyQt5.QtWidgets import *
- import sys
-
-
- class BasicQSS(QWidget):
- def __init__(self):
- super().__init__()
- self.setWindowTitle("QSS样式")
- btn1 = QPushButton(self)
- btn1.setText("按钮1")
- btn2 = QPushButton(self)
- btn2.setText("按钮2")
-
- btn3 = QPushButton(self)
- btn3.setText("按钮3")
-
- vbox = QVBoxLayout()
- vbox.addWidget(btn1)
- vbox.addWidget(btn2)
- vbox.addWidget(btn3)
-
- self.setLayout(vbox)
-
-
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- form = BasicQSS()
- # 选择器
- # 所有的QPushButton控件都设置为背景颜色为红色
- qssStyle = '''
- QPushButton {
- background-color:red
- }
- '''
- form.setStyleSheet(qssStyle)
- form.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 19:41
- from PyQt5.QtWidgets import *
- import sys
-
-
- class QSSSelector(QWidget):
- def __init__(self):
- super().__init__()
- self.setWindowTitle("QSS样式")
- btn1 = QPushButton(self)
- btn1.setText("按钮1")
- btn2 = QPushButton(self)
- # 设置name属性,可根据属性来指定按钮
- btn2.setProperty('name', 'btn2')
- btn2.setText("按钮2")
-
- btn3 = QPushButton(self)
- btn3.setProperty('name', 'btn3')
- btn3.setText("按钮3")
-
- vbox = QVBoxLayout()
- vbox.addWidget(btn1)
- vbox.addWidget(btn2)
- vbox.addWidget(btn3)
-
- self.setLayout(vbox)
-
-
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- form = QSSSelector()
- # 选择器
- # 指定按钮
- qssStyle = '''
- QPushButton[name="btn2"] {
- background-color:red;
- color:yellow;
- height:120;
- font-size:60px;
- }
- QPushButton[name="btn3"] {
- background-color:blue;
- color:yellow;
- height:60;
- font-size:30px;
- }
- '''
- form.setStyleSheet(qssStyle)
- form.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 19:46
- from PyQt5.QtWidgets import *
- import sys
-
-
- class QSSSubControl(QWidget):
- def __init__(self):
- super().__init__()
- self.setWindowTitle("QSS子控件选择器")
- combo = QComboBox(self)
- # 设置下拉框名字
- combo.setObjectName("myComboBox")
- combo.addItem("Window")
- combo.addItem("Linux")
- combo.addItem("Mac OS X")
- combo.move(50, 50)
-
- # 窗口的尺寸和位置
- self.setGeometry(250, 200, 320, 150)
-
-
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- form = QSSSubControl()
- '''
- 通过名字来引用,#myComboBox相当于web里通过id来引用
- drop-down是下拉子控件
- '''
- qssStyle = '''
- QComboBox#myComboBox::drop-down {
- image:url(./csdnlogo.jpg)
- }
- '''
- form.setStyleSheet(qssStyle)
- form.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 19:54
- from PyQt5.QtWidgets import *
- import sys
-
-
- class LabelButtonBackground(QWidget):
- def __init__(self):
- super().__init__()
- label1 = QLabel(self)
- # 鼠标放在上面就提示
- label1.setToolTip('这是一个文本标签')
- # QSS方式在label1上设置背景图
- label1.setStyleSheet('QLabel{border-image:url(./csdnlogo.jpg);}')
-
- label1.setFixedWidth(476)
- label1.setFixedHeight(259)
-
- btn1 = QPushButton(self)
- btn1.setObjectName('btn1')
- btn1.setMaximumSize(60, 60)
- btn1.setMinimumSize(60, 60)
-
- # 正常状态和按下状态时按钮图标不同
- style = '''
- #btn1{
- border-radius:4px;
- background-image:url('./csdnlogo.jpg');
- }
- #btn1:Pressed {
- background-image:url('./and.png');
- }
- '''
- btn1.setStyleSheet(style)
-
- vbox = QVBoxLayout()
- vbox.addWidget(label1)
- vbox.addStretch()
- vbox.addWidget(btn1)
-
- self.setLayout(vbox)
- self.setWindowTitle('使用QSS为标签和按钮添加背景图')
-
-
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- form = LabelButtonBackground()
- form.show()
- sys.exit(app.exec_())
这里报了一个文件找不到的错误 目前还没有解决
QSS文件 style.qss
QMainWindow{ border-image:url(./and.png); } QToolTip{ border:1px solid rgb(45,45,45); background:white; color:red }
装载类 CommonHelper.py
# @CSDN王家视频教程图书馆 # @Time 2022/11/24 20:20 #装载类 class CommonHelper: @staticmethod def readQSS(style): with open(style,'r') as f: return f.read()
loadQSS.py
# @CSDN王家视频教程图书馆 # @Time 2022/11/24 20:21 import sys from PyQt5.QtWidgets import * from CommonHelper import CommonHelper class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.resize(477, 258) self.setWindowTitle("加载QSS文件") btn = QPushButton() btn.setText('装载QSS文件') # 鼠标放到上面会有提示信息 btn.setToolTip('提示文本') vbox = QVBoxLayout() vbox.addWidget(btn) btn.clicked.connect(self.onClick) self.setLayout(vbox) widget = QWidget(self) self.setCentralWidget(widget) widget.setLayout(vbox) def onClick(self): styleFile = './style.qss' qssStyle = CommonHelper.readQSS(styleFile) win.setStyleSheet(qssStyle) if __name__ == "__main__": app = QApplication(sys.argv) win = MainWindow() win.show() sys.exit(app.exec_())
1. QSS 2. QPalette 3. 直接绘制
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 20:50
- '''
- 使用多种方式设置窗口背景色和背景图片
- 1. QSS
- 2. QPalette
- 3. 直接绘制
- '''
-
- import sys
- from PyQt5.QtWidgets import *
-
- app = QApplication(sys.argv)
- win = QMainWindow()
- win.setWindowTitle("背景图片")
- win.resize(350, 250)
- win.setObjectName("MainWindow")
-
- # 通过QSS动态修改窗口的背景颜色和背景图片
-
- win.setStyleSheet("#MainWindow{border-image:url(./csdnlogo.jpg);}")
- #win.setStyleSheet("#MainWindow{background-color:yellow}")
-
- win.show()
- sys.exit(app.exec())
-
-
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 20:54
- import sys
-
- from PyQt5.QtGui import *
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import *
-
- app = QApplication(sys.argv)
- win = QMainWindow()
- win.setWindowTitle("背景图片")
- win.resize(350, 250)
- win.setObjectName("MainWindow")
-
- # 通过QPalette设置背景图片和背景颜色
- # palette调色板
- palette = QPalette()
- # 设置画刷
- palette.setBrush(QPalette.Background, QBrush(QPixmap("./csdnlogo.jpg")))
- # palette.setColor(QPalette.Background,Qt.red)
- win.setPalette(palette)
-
- win.show()
- sys.exit(app.exec())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 20:57
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtGui import *
- from PyQt5.QtCore import *
-
-
- class Background1(QWidget):
- def __init__(self):
- super().__init__()
- self.setWindowTitle("绘制背景颜色")
-
- def paintEvent(self, event):
- painter = QPainter(self)
- painter.setBrush(Qt.yellow)
- painter.drawRect(self.rect())
-
-
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- form = Background1()
- form.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 20:58
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtGui import *
-
-
- class Background2(QWidget):
- def __init__(self):
- super().__init__()
- self.setWindowTitle("绘制背景图片")
-
- def paintEvent(self, event):
- painter = QPainter(self)
- pixmap = QPixmap('./csdnlogo.jpg')
- painter.drawPixmap(self.rect(), pixmap)
-
-
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- form = Background2()
- form.show()
- sys.exit(app.exec_())
通过mask实现异形窗口
需要一张透明的png图,透明部分被扣出,形成一个非矩形的区域
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 21:03
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtGui import *
- from PyQt5.QtCore import *
-
-
- class AbnormityWindow(QWidget):
- def __init__(self):
- super().__init__()
- self.setWindowTitle("异形窗口")
- self.pix = QBitmap('mask/mask1.png')
- self.resize(self.pix.size())
- # 设置掩膜,窗口就是掩膜的形状
- self.setMask(self.pix)
-
- def paintEvent(self, event):
- painter = QPainter(self)
- painter.drawPixmap(0, 0, self.pix.width(), self.pix.height(), QPixmap('./csdnlogo.jpg'))
-
-
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- form = AbnormityWindow()
- form.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 21:26
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtGui import *
- from PyQt5.QtCore import *
-
-
- class AbnormityWindow(QWidget):
- def __init__(self):
- super().__init__()
- self.setWindowTitle("异形窗口")
- self.pix = QBitmap('./mask/mask1.png')
- self.resize(self.pix.size())
- self.setMask(self.pix)
-
- # 鼠标按下
- def mousePressEvent(self, event):
- if event.button() == Qt.LeftButton:
- # 鼠标按下或抬起标志位
- self.m_drag = True
- # 当前单击点相对于窗口本身的坐标,永远是正的
- self.m_DragPosition = event.globalPos() - self.pos()
- # print(self.m_DragPosition)
- # 设置光标形状
- self.setCursor(QCursor(Qt.OpenHandCursor))
- '''
- # 当前单击点相对于屏幕的坐标,包括标题栏和边框
- print(event.globalPos())
- # 当前单击点相对于窗口的坐标,忽略标题栏和边框
- print(event.pos())
- '''
- # 左上角坐标相对于屏幕的坐标,包括标题栏和边框
- print(self.pos())
- # 按下右键
- if event.button() == Qt.RightButton:
- self.close()
-
- # 鼠标移动
- def mouseMoveEvent(self, QMouseEvent):
- if Qt.LeftButton and self.m_drag:
- # 当左键移动窗体修改偏移值
- # QPoint
- '''
- 实时计算窗口左上角坐标,注意是左上角!!!!!!
- 这个移动是从上次的窗口位置往现在到达的位置移动,
- 所以是现在的globalPos()减去移动之前的单击点到窗口边框的距离,就是当前左上角坐标
- '''
- self.move(QMouseEvent.globalPos() - self.m_DragPosition)
-
- # 鼠标抬起
- def mouseReleaseEvent(self, QMouseEvent):
- self.m_drag = False
- # cursor(n.)光标
- self.setCursor(QCursor(Qt.ArrowCursor))
-
- def paintEvent(self, event):
- painter = QPainter(self)
- painter.drawPixmap(0, 0, self.pix.width(), self.pix.height(), QPixmap('./csdnlogo.jpg'))
-
-
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- form = AbnormityWindow()
- form.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 21:48
- import sys
- from PyQt5.QtWidgets import QApplication, QWidget
- from PyQt5.QtGui import QPixmap, QPainter, QCursor
- from PyQt5.QtCore import Qt, QTimer
-
-
- class AnimationWindows(QWidget):
- def __init__(self, parent=None):
- super(AnimationWindows, self).__init__(parent)
- self.i = 1
- self.mypix() # 显示第一张的图
- self.timer = QTimer() # 定时器
- self.timer.setInterval(500) # 即500毫秒换一帧
- self.timer.timeout.connect(self.timeChange)
- self.timer.start()
-
- # 显示不规则 pic
- def mypix(self):
- # 通过立即调用paintEvent()来直接重新绘制窗口部件
- self.update()
- if self.i == 5:
- self.i = 1
- self.mypic = {1: './rotate/left.png', 2: "./rotate/top.png", 3: './rotate/right.png',
- 4: './rotate/buttom.png'}
- self.pix = QPixmap(self.mypic[self.i])
- self.resize(self.pix.size())
- # 设置掩膜
- self.setMask(self.pix.mask())
- self.dragPosition = None
-
- def mousePressEvent(self, event):
- if event.button() == Qt.LeftButton:
- self.m_drag = True
- self.m_DragPosition = event.globalPos() - self.pos()
- # 设置光标形状
- self.setCursor(QCursor(Qt.OpenHandCursor))
-
- def mouseMoveEvent(self, QMouseEvent):
- if Qt.LeftButton and self.m_drag:
- self.move(QMouseEvent.globalPos() - self.m_DragPosition)
-
- def mouseReleaseEvent(self, QMouseEvent):
- self.m_drag = False
- self.setCursor(QCursor(Qt.ArrowCursor))
-
- def paintEvent(self, event):
- painter = QPainter(self)
- painter.drawPixmap(0, 0, self.pix.width(), self.pix.height(), self.pix)
-
- # 鼠标双击事件
- def mouseDoubleClickEvent(self, event):
- if event.button() == 1:
- self.i += 1
- self.mypix()
-
- # 每500毫秒修改paint,即换一张图
- def timeChange(self):
- self.i += 1
- self.mypix()
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- form = AnimationWindows()
- form.show()
- sys.exit(app.exec_())
效果暂时没有显示出来,后续测试
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 22:08
- import sys
- from PyQt5.QtWidgets import QApplication,QLabel,QWidget
- from PyQt5.QtCore import Qt
- from PyQt5.QtGui import QMovie
-
-
-
- class loadingGif(QWidget):
- def __init__(self):
- super(loadingGif, self).__init__()
- self.label = QLabel("", self)
- self.setFixedSize(128, 128)
- self.setWindowFlags(Qt.Dialog | Qt.CustomizeWindowHint)
- self.movie = QMovie('../loding2.gif')
- self.label.setMovie(self.movie)
- self.movie.start()
-
-
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- form = loadingGif()
- form.show()
- sys.exit(app.exec_())
QImage.scaled
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 22:39
- from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout
- from PyQt5.QtGui import QImage, QPixmap
- from PyQt5.QtCore import Qt
- import sys
-
-
- class ScaleImage(QWidget):
- def __init__(self):
- super().__init__()
- self.setWindowTitle("图片大小缩放例子")
- filename = './csdnlogo.jpg'
- img = QImage(filename)
- label1 = QLabel(self)
- label1.setFixedWidth(200)
- label1.setFixedHeight(200)
-
- # 参数三四:忽略比例,平滑显示
- result = img.scaled(label1.width(), label1.height(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
- label1.setPixmap(QPixmap.fromImage(result))
-
- vbox = QVBoxLayout()
- vbox.addWidget(label1)
-
- self.setLayout(vbox)
-
-
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- win = ScaleImage()
- win.show()
- sys.exit(app.exec_())
QPropertyAnimation可以控制任何可视控件的尺寸的动态的变化,只要我们把控件的对象通过构造方法传入即可
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 22:48
- from PyQt5.QtCore import *
- from PyQt5.QtWidgets import *
- import sys
-
-
- class AnimWindow(QWidget):
- def __init__(self):
- super(AnimWindow, self).__init__()
- self.OrigHeight = 50
- self.ChangeHeight = 150
- self.setGeometry(QRect(500, 400, 150, self.OrigHeight))
- self.btn = QPushButton('展开', self) # 没用布局,直接将按钮放入
- self.btn.setGeometry(10, 10, 60, 35)
-
- self.btn.clicked.connect(self.change)
-
- def change(self):
- currentHeight = self.height()
- if self.OrigHeight == currentHeight:
- startHeight = self.OrigHeight
- endHeight = self.ChangeHeight
- self.btn.setText('收缩')
- else:
- startHeight = self.ChangeHeight
- endHeight = self.OrigHeight
- self.btn.setText('展开')
-
- self.animation = QPropertyAnimation(self, b'geometry') # 将当前窗口传入
- self.animation.setDuration(500) # 间隔时间:500毫秒
- # 初始尺寸
- self.animation.setStartValue(QRect(500, 400, 150, startHeight))
- # 变化后的尺寸
- self.animation.setEndValue(QRect(500, 400, 150, endHeight))
- self.animation.start()
-
- return
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- window = AnimWindow()
- window.show()
- sys.exit(app.exec_())
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/24 22:55
- from PyQt5.QtGui import *
- from PyQt5.QtCore import *
- from PyQt5.QtWidgets import *
- import sys
-
- app = QApplication(sys.argv)
-
- window1 = QMainWindow()
- window1.show()
- window2 = QMainWindow()
- window2.show()
-
- animation1 = QPropertyAnimation(window1, b'geometry')
- animation2 = QPropertyAnimation(window2, b'geometry')
-
- group = QParallelAnimationGroup() # 并行 动画组 并行,同时运行多个动画
- # group = QSequentialAnimationGroup() # 串行
-
- group.addAnimation(animation1)
- group.addAnimation(animation2)
-
- animation1.setDuration(3000)
- animation1.setStartValue(QRect(0, 0, 100, 30))
- animation1.setEndValue(QRect(250, 250, 100, 30))
- animation1.setEasingCurve(QEasingCurve.OutBounce) # 动画特效
-
- animation2.setDuration(4000)
- animation2.setStartValue(QRect(250, 150, 100, 30))
- animation2.setEndValue(QRect(850, 250, 100, 30))
- animation2.setEasingCurve(QEasingCurve.CosineCurve)
-
- group.start()
-
- sys.exit(app.exec())
安装:pip3 install pyinstaller
代码:
直接在命令行下操作
常用:pyinstaller -Fw python文件名
pyinstaller -Fw Calc. py
-W:不显示终端
-F:将所有的库打包成-个单独的文件
pip3 install pyinstaller安装
使用pyinstaller查看可选参数
开始打包 pyinstaller -Fw .\ScaleImage.py
打包程序完成
打包成功后项目目录下多了两个文件夹,包括build和dist。exe文件就存在于dist目录下。将文件中调用的文件手动放到exe同目录下。双击exe文件运行即可!
#轻量级数据库,支持多种接口,跨平台
#现在很多移动应用 安卓 iOS 都使用SQLite作为本地数据库
#本地数据库只需要提供文件名,而不需要IP,用户名,密码啥的
#数据库可视化工具DB Browser for SQLite:
右键运行生成数据库db文件
QTableView
QSql TableModel
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/25 0:27
- import sys
- from PyQt5.QtCore import *
- from PyQt5.QtGui import *
- from PyQt5.QtWidgets import *
- from PyQt5.QtSql import *
-
-
- # 初始化
- def initializeModel(model):
- model.setTable('people')
- # 当字段变化时会触发一些事件
- model.setEditStrategy(QSqlTableModel.OnFieldChange)
- # 将整个数据装载到model中
- model.select()
- # 设置字段头
- model.setHeaderData(0, Qt.Horizontal, 'ID')
- model.setHeaderData(1, Qt.Horizontal, '姓名')
- model.setHeaderData(2, Qt.Horizontal, '地址')
-
-
- # 创建视图
- def createView(title, model):
- view = QTableView()
- view.setModel(model)
- view.setWindowTitle(title)
- return view
-
-
- def findrow(i):
- # 当前选中的行
- delrow = i.row()
- print('del row=%s' % str(delrow))
-
-
- def addrow():
- # 不是在QTableView上添加,而是在模型上添加,会自动将数据保存到数据库中!
- # 参数一:数据库共有几行数据 参数二:添加几行
- ret = model.insertRows(model.rowCount(), 1) # 返回是否插入
- print('数据库共有%d行数据' % model.rowCount())
- print('insertRow=%s' % str(ret))
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- db = QSqlDatabase.addDatabase('QSQLITE')
- db.setDatabaseName('./db1.db')
- model = QSqlTableModel() # MVC模式中的模型
- delrow = -1
- # 初始化将数据装载到模型当中
- initializeModel(model)
- view = createView("展示数据", model)
- view.clicked.connect(findrow)
-
- dlg = QDialog()
- layout = QVBoxLayout()
- layout.addWidget(view)
- addBtn = QPushButton('添加一行')
- addBtn.clicked.connect(addrow)
-
- delBtn = QPushButton('删除一行')
- delBtn.clicked.connect(lambda: model.removeRow(view.currentIndex().row()))
-
- layout.addWidget(view)
- layout.addWidget(addBtn)
- layout.addWidget(delBtn)
- dlg.setLayout(layout)
- dlg.setWindowTitle("Database Demo")
- dlg.resize(500, 400)
- dlg.show()
- sys.exit(app.exec())
limit关键字
limit n,m
n是起始点(不含),m是偏移量,例如 limit 10,20代表从11开始的20条数据,即11-30
- # @CSDN王家视频教程图书馆
- # @Time 2022/11/25 0:58
- import sys
- from PyQt5.QtWidgets import *
- from PyQt5.QtCore import Qt
- from PyQt5.QtSql import *
-
-
- class DataGrid(QWidget):
- def createTableAndInit(self):
- # 添加数据库
- self.db = QSqlDatabase.addDatabase('QSQLITE')
- # 设置数据库名称
- self.db.setDatabaseName('./database.db')
- # 判断是否打开
- if not self.db.open():
- return False
-
- # 声明数据库查询对象
- query = QSqlQuery()
- # 创建表
- query.exec("create table student(id int primary key, name vchar, sex vchar, age int, deparment vchar)")
-
- # 添加记录
- query.exec("insert into student values(1,'张三1','男',20,'计算机')")
- query.exec("insert into student values(2,'李四1','男',19,'经管')")
- query.exec("insert into student values(3,'王五1','男',22,'机械')")
- query.exec("insert into student values(4,'赵六1','男',21,'法律')")
- query.exec("insert into student values(5,'小明1','男',20,'英语')")
- query.exec("insert into student values(6,'小李1','女',19,'计算机')")
- query.exec("insert into student values(7,'小张1','男',20,'机械')")
- query.exec("insert into student values(8,'小刚1','男',19,'经管')")
- query.exec("insert into student values(9,'张三2','男',21,'计算机')")
- query.exec("insert into student values(10,'张三3','女',20,'法律')")
- query.exec("insert into student values(11,'王五2','男',19,'经管')")
- query.exec("insert into student values(12,'张三4','男',20,'计算机')")
- query.exec("insert into student values(13,'小李2','男',20,'机械')")
- query.exec("insert into student values(14,'李四2','女',19,'经管')")
- query.exec("insert into student values(15,'赵六3','男',21,'英语')")
- query.exec("insert into student values(16,'李四2','男',19,'法律')")
- query.exec("insert into student values(17,'小张2','女',22,'经管')")
- query.exec("insert into student values(18,'李四3','男',21,'英语')")
- query.exec("insert into student values(19,'小李3','女',19,'法律')")
- query.exec("insert into student values(20,'王五3','女',20,'机械')")
- query.exec("insert into student values(21,'张三4','男',22,'计算机')")
- query.exec("insert into student values(22,'小李2','男',20,'法律')")
- query.exec("insert into student values(23,'张三5','男',19,'经管')")
- query.exec("insert into student values(24,'小张3','女',20,'计算机')")
- query.exec("insert into student values(25,'李四4','男',22,'英语')")
- query.exec("insert into student values(26,'赵六2','男',20,'机械')")
- query.exec("insert into student values(27,'小李3','女',19,'英语')")
- query.exec("insert into student values(28,'王五4','男',21,'经管')")
-
- return True
-
- def __init__(self):
- super().__init__()
- self.setWindowTitle("分页查询例子")
- self.resize(750, 350)
- self.createTableAndInit()
-
- # 当前页
- self.currentPage = 0
- # 总页数
- self.totalPage = 0
- # 总记录数
- self.totalRecrodCount = 0
- # 每页显示记录数
- self.PageRecordCount = 6
-
- self.initUI()
-
- def initUI(self):
- # 创建窗口
- self.createWindow()
- # 设置表格
- self.setTableView()
-
- # 信号槽连接
- self.prevButton.clicked.connect(self.onPrevButtonClick)
- self.nextButton.clicked.connect(self.onNextButtonClick)
- self.switchPageButton.clicked.connect(self.onSwitchPageButtonClick)
-
- def closeEvent(self, event):
- # 关闭数据库
- self.db.close()
-
- # 创建窗口
- def createWindow(self):
- # 操作布局
- operatorLayout = QHBoxLayout()
- self.prevButton = QPushButton("前一页")
- self.nextButton = QPushButton("后一页")
- self.switchPageButton = QPushButton("Go")
- self.switchPageLineEdit = QLineEdit()
- self.switchPageLineEdit.setFixedWidth(40)
-
- switchPage = QLabel("转到第")
- page = QLabel("页")
- operatorLayout.addWidget(self.prevButton)
- operatorLayout.addWidget(self.nextButton)
- operatorLayout.addWidget(switchPage)
- operatorLayout.addWidget(self.switchPageLineEdit)
- operatorLayout.addWidget(page)
- operatorLayout.addWidget(self.switchPageButton)
- operatorLayout.addWidget(QSplitter())
-
- # 状态布局
- statusLayout = QHBoxLayout()
- self.totalPageLabel = QLabel()
- self.totalPageLabel.setFixedWidth(70)
- self.currentPageLabel = QLabel()
- self.currentPageLabel.setFixedWidth(70)
-
- self.totalRecordLabel = QLabel()
- self.totalRecordLabel.setFixedWidth(70)
-
- statusLayout.addWidget(self.totalPageLabel)
- statusLayout.addWidget(self.currentPageLabel)
- statusLayout.addWidget(QSplitter())
- statusLayout.addWidget(self.totalRecordLabel)
-
- # 设置表格属性
- self.tableView = QTableView()
- # 表格宽度的自适应调整
- self.tableView.horizontalHeader().setStretchLastSection(True)
- self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
-
- # 创建界面
- mainLayout = QVBoxLayout(self);
- mainLayout.addLayout(operatorLayout);
- mainLayout.addWidget(self.tableView);
- mainLayout.addLayout(statusLayout);
- self.setLayout(mainLayout)
-
- # 设置表格
- def setTableView(self):
-
- # 声明查询模型
- self.queryModel = QSqlQueryModel(self)
- # 设置当前页
- self.currentPage = 1;
- # 得到总记录数
- self.totalRecrodCount = self.getTotalRecordCount()
- # 得到总页数
- self.totalPage = self.getPageCount()
- # 刷新状态
- self.updateStatus()
- # 设置总页数文本
- self.setTotalPageLabel()
- # 设置总记录数
- self.setTotalRecordLabel()
-
- # 记录查询
- self.recordQuery(0)
- # 设置模型
- self.tableView.setModel(self.queryModel)
-
- print('totalRecrodCount=' + str(self.totalRecrodCount))
- print('totalPage=' + str(self.totalPage))
-
- # 设置表格表头
- self.queryModel.setHeaderData(0, Qt.Horizontal, "编号")
- self.queryModel.setHeaderData(1, Qt.Horizontal, "姓名")
- self.queryModel.setHeaderData(2, Qt.Horizontal, "性别")
- self.queryModel.setHeaderData(3, Qt.Horizontal, "年龄")
- self.queryModel.setHeaderData(4, Qt.Horizontal, "院系")
-
- # 得到记录数
- def getTotalRecordCount(self):
- self.queryModel.setQuery("select * from student")
- rowCount = self.queryModel.rowCount()
- print('rowCount=' + str(rowCount))
- return rowCount
-
- # 得到页数
- def getPageCount(self):
- if self.totalRecrodCount % self.PageRecordCount == 0:
- return (self.totalRecrodCount / self.PageRecordCount)
- else:
- return (self.totalRecrodCount / self.PageRecordCount + 1)
-
- # 记录查询
- def recordQuery(self, limitIndex):
- szQuery = ("select * from student limit %d,%d" % (limitIndex, self.PageRecordCount))
- print('query sql=' + szQuery)
- self.queryModel.setQuery(szQuery)
-
- # 刷新状态
- def updateStatus(self):
- szCurrentText = ("当前第%d页" % self.currentPage)
- self.currentPageLabel.setText(szCurrentText)
-
- # 设置按钮是否可用
- if self.currentPage == 1:
- self.prevButton.setEnabled(False)
- self.nextButton.setEnabled(True)
- elif self.currentPage == self.totalPage:
- self.prevButton.setEnabled(True)
- self.nextButton.setEnabled(False)
- else:
- self.prevButton.setEnabled(True)
- self.nextButton.setEnabled(True)
-
- # 设置总数页文本
- def setTotalPageLabel(self):
- szPageCountText = ("总共%d页" % self.totalPage)
- self.totalPageLabel.setText(szPageCountText)
-
- # 设置总记录数
- def setTotalRecordLabel(self):
- szTotalRecordText = ("共%d条" % self.totalRecrodCount)
- print('*** setTotalRecordLabel szTotalRecordText=' + szTotalRecordText)
- self.totalRecordLabel.setText(szTotalRecordText)
-
- # 前一页按钮按下
- def onPrevButtonClick(self):
- print('*** onPrevButtonClick ');
- limitIndex = (self.currentPage - 2) * self.PageRecordCount
- self.recordQuery(limitIndex)
- self.currentPage -= 1
- self.updateStatus()
-
- # 后一页按钮按下
- def onNextButtonClick(self):
- print('*** onNextButtonClick ');
- limitIndex = self.currentPage * self.PageRecordCount
- self.recordQuery(limitIndex)
- self.currentPage += 1
- self.updateStatus()
-
- # 转到页按钮按下
- def onSwitchPageButtonClick(self):
- # 得到输入字符串
- szText = self.switchPageLineEdit.text()
-
- # 得到页数
- pageIndex = int(szText)
- # 判断是否有指定页
- if pageIndex > self.totalPage or pageIndex < 1:
- QMessageBox.information(self, "提示", "没有指定的页面,请重新输入")
- return
-
- # 得到查询起始行号
- limitIndex = (pageIndex - 1) * self.PageRecordCount
-
- # 记录查询
- self.recordQuery(limitIndex);
- # 设置当前页
- self.currentPage = pageIndex
- # 刷新状态
- self.updateStatus();
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- # 创建窗口
- example = DataGrid()
- # 显示窗口
- example.show()
- sys.exit(app.exec_())
首先安装 pip3 install pyqtgraph
右键运行报错 暂未解决!
pyqtgraph_pyqt.py
# @CSDN王家视频教程图书馆 # @Time 2022/11/25 1:15 # -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'pyqtgraph_pyqt.ui' # # Created by: PyQt5 UI code generator 5.9.2 # # WARNING! All changes made in this file will be lost! from PyQt5 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 600) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.pyqtgraph1 = GraphicsLayoutWidget(self.centralwidget) self.pyqtgraph1.setGeometry(QtCore.QRect(10, 10, 721, 251)) self.pyqtgraph1.setObjectName("pyqtgraph1") self.pyqtgraph2 = GraphicsLayoutWidget(self.centralwidget) self.pyqtgraph2.setGeometry(QtCore.QRect(10, 290, 501, 281)) self.pyqtgraph2.setObjectName("pyqtgraph2") MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) from pyqtgraph import GraphicsLayoutWidget
Graph.py
# @CSDN王家视频教程图书馆 # @Time 2022/11/25 1:16 ''' 使用PyQtGraph绘图 pip Install pyqtgraph ''' from PyQt5.QtCore import pyqtSlot from PyQt5.QtWidgets import QMainWindow, QApplication import pyqtgraph as pg from pyqtgraph_pyqt import Ui_MainWindow import numpy as np class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) pg.setConfigOption('background', '#f0f0f0') pg.setConfigOption('foreground', 'd') self.setupUi(self) self.draw1() self.draw2() def draw1(self): self.pyqtgraph1.clear() '''第一种绘图方式''' print(np.random.normal(size=120)) self.pyqtgraph1.addPlot(title="绘图单条线", y=np.random.normal(size=120), pen=pg.mkPen(color='b', width=2)) '''第二种绘图方式''' plt2 = self.pyqtgraph1.addPlot(title='绘制多条线') plt2.plot(np.random.normal(size=150), pen=pg.mkPen(color='r', width=2), name="Red curve") plt2.plot(np.random.normal(size=110) + 5, pen=(0, 255, 0), name="Green curve") plt2.plot(np.random.normal(size=120) + 10, pen=(0, 0, 255), name="Blue curve") def draw2(self): plt = self.pyqtgraph2.addPlot(title='绘制条状图') x = np.arange(10) print(x) y1 = np.sin(x) y2 = 1.1 * np.sin(x + 1) y3 = 1.2 * np.sin(x + 2) bg1 = pg.BarGraphItem(x=x, height=y1, width=0.3, brush='r') bg2 = pg.BarGraphItem(x=x + 0.33, height=y2, width=0.3, brush='g') bg3 = pg.BarGraphItem(x=x + 0.66, height=y3, width=0.3, brush='b') plt.addItem(bg1) plt.addItem(bg2) plt.addItem(bg3) self.pyqtgraph2.nextRow() p4 = self.pyqtgraph2.addPlot(title="参数图+显示网格") x = np.cos(np.linspace(0, 2 * np.pi, 1000)) y = np.sin(np.linspace(0, 4 * np.pi, 1000)) p4.plot(x, y, pen=pg.mkPen(color='d', width=2)) # p4.showGrid(x=True, y=True) # 显示网格 if __name__ == "__main__": import sys app = QApplication(sys.argv) ui = MainWindow() ui.show() sys.exit(app.exec_())
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。