PYQT5 系列(一)——参考自《弗兰克万岁》
源:简书地址-------------->弗兰克万岁<--------------简书地址
PYQT5 (一)MAIN.PY标准开局
1 import sys 2 from PyQt5.QtWidgets import QApplication 3 4 from lib.main_window import main_window 5 6 if __name__=='__main__': 7 app = QApplication(sys.argv) 8 m=main_window() 9 sys.exit(app.exec_())
PYQT5(二)解决子线程闪退的问题
一般情况下是因为你的window没有保存好导致的 举个例子: 我在一个class 为 test的窗口类中写了一个方法 def createNewWindow(self): newWindow=QDialog() testWindow=MyPersonalPrograme(newWindow) 如果你这么写的话一般来讲,窗口都是一闪而逝的,可以试试改为 def createNewWindow(self): self.newWindow=QDialog() testWindow=MyPersonalPrograme(self.newWindow)
PYQT5(三)设置窗口背景颜色和无边框属性,和置顶
#在窗口初始化的时候加入就可以了 #self.window是QMainWindow() from PyQt5.QtWidgets import QApplication,QMainWindow from PyQt5 import QtGui, QtCore palette1 = QtGui.QPalette() palette1.setColor(palette1.Background,QtGui.QColor(255,255,255)) self.window.setPalette(palette1) window.setWindowFlags(Qt.Qt.FramelessWindowHint|Qt.Qt.WindowStaysOnTopHint)#无边框,置顶 self.window.setAttribute(Qt.Qt.WA_TranslucentBackground)#透明背景色
PYQT5(四)PYCHARM配置
此篇可以详见源:https://www.jianshu.com/p/b5322f8cdcd1
亦可参考我之前的博客:https://www.cnblogs.com/wohuiyijiu/p/12454130.html
(五没找着...)
PYQT5(六)ListWidget列表视图添加按钮以及绑定事件
def GenerateBtn(self,pid): viewBtn = QtWidgets.QPushButton('查看') viewBtn.setStyleSheet(''' text-align : center; background-color : DarkSeaGreen; height : 30px; border-style: outset; color:white; font : 13px; ''') viewBtn.clicked.connect(lambda:self.jump(pid)) return viewBtn
def jump(self,pid): if id: self.son.pid=pid if not self.window.isVisible(): self.son.window.hide() self.window.show() else: self.window.hide() self.son.window.show() self.sql.log(4,self.guige, pid) self.son.accept() def buttonForRow(self,res): # 列表控件QTableWidget生成列表 self.result_list.clear()#result_list就是Qtablewidget for i in range(0,len(res)): item =self.result_list.horizontalHeaderItem(i) self.result_list.setHorizontalHeaderItem(i, item) self.result_list.setItem(i,0,QtWidgets.QTableWidgetItem(str(res[i][0]))) self.result_list.setItem(i,1, QtWidgets.QTableWidgetItem(str(res[i][1]))) btn=self.GenerateBtn(res[i][1]) self.result_list.setCellWidget(i,2,btn)
PYQT5(七)QComboBox下拉菜单
下拉菜单的控件名称是QComboBox() 先引入PyQt5.QtWidgets 然后就可以通过QtWidgets 引入QcomboBox了 -------------------------------------------------- from PyQt5.QtWidgets import QApplication,QMainWindow,QDialog if __name__ == '__main__': app = QApplication(sys.argv) QDialog = QDialog() s=Dialog(QDialog)#Dialog类是自己写的,初始化类 QDialog.show() sys.exit(app.exec_()) -------------------------------------------------- self.country_box = QtWidgets.QComboBox(Dialog)#Dialog从初始化的时候传参进来放在这里使用 self.country_box.setGeometry(QtCore.QRect(850,231,291,31)) self.country_box.setObjectName("country_box") self.country_box.addItem("")#先添加一个下拉菜单空位 -------------------------------------------------- self.combo_box.setItemText(0, _translate("Dialog","test combo value"))#该函数只能设置内容,不能新增 -------------------------------------------------- self.country_box.setItemText(1, _translate("Dialog","test 2")) -------------------------------------------------- 如果要新增的话可以直接使用addItem("这里填入文本内容") -------------------------------------------------- self.country_box.currentText()#发生变动后获取当前选择的内容 -------------------------------------------------- 附上常用函数 重载(动态修改内容) insertItem() setItemText() 如果组合框的当前项目发生更改(状态改变) currentIndexChanged() activated() highlighted() 移除内容 removeItem() clear() 获取当前内容 currentText() 绑定事件 self.combobox.currentIndexChanged.connect(self.action)
PYQT5(八)QCheckBox复选框使用范例
首先创建一个布局,这一段是pyqt5自带的编辑器生成的 --------------------------------------------- self.gridLayoutWidget = QtWidgets.QWidget(QDialog) self.gridLayoutWidget.setGeometry(QtCore.QRect(830,140,321,141)) self.gridLayoutWidget.setObjectName("gridLayoutWidget") self.model_gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget) self.model_gridLayout.setContentsMargins(0,0,0,0) self.model_gridLayout.setObjectName("model_gridLayout") 然后再初始化,添加各种数值,因为checkbox比较多,这里用的一个数组循环赋值 --------------------------------------------- for i in data: if i[0]: if index<4: checkbox = QtWidgets.QCheckBox(i[0]+'-'+i[1],self.gridLayoutWidget) self.model_girdlayout.addWiget(checkbox,x,index,1,1) index+=1 else: index=0 x+=1 self.model_widgets.append(checkbox) model_widgets是用来保存每一个checkbox的,所以不要忘了先初始化变量 如果出现在循环体中绑定点击事件,发生事件混乱现象,可以将创建checkbox再封装一层方法,便可以解决问题。 --------------------------------------------- def create_checkboc(self,name,id): checkbox = QtWidgets.QCheckBox(name+'-'+id,self.gridLayoutWidget) checkbox.stateChanged.connect(lambda : self.show(name,id)) return checkbox --------------------------------------------- 关闭checkbox可以按照如下方法 close() 关闭复选框(并未彻底丢弃) deleteLater()删除复选框) 附上checkbox的一些常用函数 isChecked()判断函数是否被选中 setChecked()设置是否选择,True为选中。
PYQT5(九)pyinstaller打包运行报错failed to execute script main,缺少queue包
pyqt5写完win32 应用程序后,经过pyinstaller打包成单个文件,运行弹出错误提示框:failed to execute script main pycharm中pyinstaller打包参数: Program:C:\Python\Python35\Scripts\pyinstaller.exe Parameters: -w -F $FileName$ Working directory: $FileDir$ 分析: 经google,发现pyinstaller 有--hidden-import 选项 --hidden-import MODULENAME, --hiddenimport MODULENAME Name an import not visible in the code of the script(s). This option can be used multiple times. 解决: 打包时加上 --hidden-import=queue 即Parameters配置修改为: Parameters:--hidden-import=queue -w -F $FileName$ eg: pyinstaller --hidden-import=queue -w -F -i test.ico main.py 问题2: ImportError: No module named ‘queue‘ Failed to execute script final_exam2 然后自己手工导入queue模块,并没有报错。 打包时加上 --hidden-import=queue 在尝试重新打包并且使用--hidden-import queue 后,程序能够正常运行。
PYQT5(十)解决win10向下兼容xp的问题
更新于2020年2月17日 关于开发兼容windowsxp系统,并使用pyinstaller 打包的pyqt5软件。 如果有成功在win10系统编译,同时在xp系统上跑的大神,麻烦艾特我教我一下,或者有正在研究的可以找我讨论一下,网上的资料基本上是坑人的,或者抄来抄去的。 目前来看,最好的方案具体操作步骤如下: 在虚拟机中跑一个xp(如果有xp系统的机子当然更好啦) 我用是virtualbox 2.下载python3.4版本(xp系统最高支持到python3.4) 链接就不上了,直接百度搜索python就有一大堆。 安装pywin32 https://sourceforge.net/projects/pywin32/files/pywin32/Build%20220/pywin32-220.win32-py3.4.exe/download 然后点击安装pywin32的安装文件 安装Pyinstaller3.2.1 ------------------------------------------- 安装命令:pip install pyinstaller==3.2.1 ------------------------------------------- 到下面的连接中下载pyqt5 python3.4 专用版 附上链接,注意检查位数,我用的是32位的。 这里贴上一个5.5.1的版本,亲测可用。 https://sourceforge.net/projects/pyqt/files/PyQt5/PyQt-5.5.1/ by the way 如果安装失败的话,也可以试试 试试 pip install python-qt5 使用exe文件安装后,pip list 中不显示pyqt5 网上说是python 32位和pyqt5的exe包对不上。 结合本人尝试,使用Pyqt5-5.5.1的版本的对应位数的安装包,安装后别管list,直接打包也可以 打包测试 贴上pyinstaller的简单使用教程 ------------------------------------------- pyinstaller -p C:\Python34\Lib\site-packages\PyQt5 -F -w main.py** -p 搜索额外的库文件地址 -F 注意大小写,生成的文件是单个exe执行文件 -w 无console窗口 ------------------------------------------- 常见错误 ------------------------------------------- from PyQt5 import QtCore, QtGui, QtWidgets ImportError: cannot import name 'QtCore' ------------------------------------------- 据说别的版本的pyinstaller各种bug,网络上的那些抄来抄去的博客没什么好看的,说有bug但是不说是什么bug,无非就是找不到你的pyqt库的bug。 估计是上一步有问题,可以在cmd里试试 ------------------------------------------- pip uninstall pyinstaller pip install pyinstaller==3.2.1 ------------------------------------------- 所以最好还是下载pyinstaller3.2.1 ------------------------------------------- no model name 'queue' ------------------------------------------- pyinstaller -F --hidden-import=queue final_exam2.py ------------------------------------------- pip install openpyxl 失败的解决方法 ------------------------------------------- pip install openpyxl==2.5.14
PYQT5(十一)实现右键菜单
窗体绑定右键事件 ---------------------------------------------- self.window.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.window.customContextMenuRequested.connect(self.rightMenuShow) ---------------------------------------------- 设置右键菜单事件,和后续的动作 ---------------------------------------------- def rightMenuShow(self): try: self.contextMenu = QMenu() self.actionA = self.contextMenu.addAction(u'动作a') self.contextMenu.popup(QCursor.pos()) # 2菜单显示的位置 self.actionA.triggered.connect(self.actionHandler) self.contextMenu.show() except Exception as e: print(e) def actionHandler(self): print('action')
PYQT5 (十二)图片控件,截图功能
主要是使用Qlabel来实现 ---------------------------------------------- 获取宽度:Qlabel.width() 获取高度:Qlabel.height() ---------------------------------------------- def cut(self): screen = QApplication.primaryScreen() # pix = screen.grabWindow(self.window.winId()) pix = screen.grabWindow(self.img_label.winId()) pix.save("test.jpg") ---------------------------------------------- 图片太大的解决方法: ---------------------------------------------- self.scrollArea = QtWidgets.QScrollArea(self.centralwidget) self.scrollArea.setGeometry(QtCore.QRect(20,60,841,591)) self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName("scrollArea") self.MyScroll = QtWidgets.QWidget() self.MyScroll.setGeometry(QtCore.QRect(0,0,839,589)) self.MyScroll.setObjectName("MyScroll") self.MyScroll.setMinimumSize(7000,7000) #scrollArea就对了 ---------------------------------------------- 图片控件(QImage) ---------------------------------------------- def pic(self): # print(self.window.size) pix = QPixmap('icon/123.png') scale=1 print(pix.width()) if pix.width() self.img_label.setGeometry(10,10,pix.width()*scale,pix.height()*scale) else: self.img_label.setScaledContents(True) # self.img_label.setGeometry(10, 10, self.width*scale, self.height*scale) self.img_label.setStyleSheet("border: 2px solid red") self.img_label.setPixmap(pix) # self.img_label.mouseDoubleClickEvent(self.zoom())
PYQT5(十三)配合微信截图并保存图片
# -*- coding:utf-8 -*- import ctypes import os from PyQt5.QtWidgets import QApplication def capture(): clipboard=QApplication.clipboard() try: dll = ctypes.cdll.LoadLibrary('PrScrn.dll') dataImage = clipboard.pixmap() dataImage.save('Grab.png') except Exception: print("Dll load error!") return else: try: dll.PrScrn(0) dataImage = clipboard.pixmap() dataImage.save('Grab.png') except Exception: print("Sth wrong in capture!") return
PYQT5 (十四)配合PILLOW使用
主要解决两种不同的库之间图片来回调用问题。 添加logo------------------------------- im = Image.open(path) im = im.convert("RGBA") im=im.resize((600,500),Image.ANTIALIAS) try: mark = Image.open("image/logo.png") s=im.size layer = Image.new('RGBA', s, (0, 0, 0, 0))#底层画布 layer.paste(mark, (int((s[0]-mark.size[0])/2) , int((s[1]-mark.size[1])/2)))#添加水印 out = Image.composite(layer, im, layer)#整合在一起 data = out.tobytes("raw", "RGBA")#转换成byte格式 qim = QtGui.QImage(data, s[0], s[1], QtGui.QImage.Format_RGBA8888)#转换成qimage格式 qim.save('tttt.jpg')#保存在本地 return qim#同时返回 # pix=QtGui.QPixmap.fromImage(qim) except Exception as e: print('error',e) 添加透明度------------------------------- #有bug mark.putalpha(50) https://www.cnblogs.com/RChen/archive/2007/03/31/pil_thumb.html
PYQT5(十五) pushbutton绑定事件
self.setting_btn.clicked.connect(lambda :init_setting(self))
PYQT5(十六)图片容器
def pic(self): # print(self.window.size) pix = QPixmap('icon/123.png') scale=1 if pix.width()<self.width:#对比宽度 self.img_label.setGeometry(10,10,pix.width()*scale,pix.height()*scale) else: self.img_label.setScaledContents(True) # self.img_label.setGeometry(10, 10, self.width*scale, self.height*scale) self.img_label.setStyleSheet("border: 2px solid red") self.img_label.setPixmap(pix) # self.img_label.mouseDoubleClickEvent(self.zoom())
PYQT5(十七)打开文件目录
def setPicPath(self): path=self.load_last_path() file=QDialog() fname,ftype=QFileDialog.getOpenFileName(file,'open',path) print(fname) if fname: res = self.save_last_path(fname) if res == 0: print('false occured in path saving processing')
如果要获取地址或者别的可以试试下面这些函数
getOpenFileNames 获取多个文件的地址,返回的是一个数组
getOpenFileUrl 返回PyQt5.QtCore.QUrl 对象,不知道什么用途
PYQT5 (十八)文件拖放(drag and drop)并获取文件信息
#通过重写QScrollArea 类实现的文件拖拽操作 class MyScrollWidget(QtWidgets.QScrollArea): def __init__(self,parent=None): super().__init__(parent) self.setAcceptDrops(True) def dragEnterEvent(self, event): if event.mimeData().hasUrls: event.accept() else: event.ignore() def dragMoveEvent(self, event): if event.mimeData().hasUrls: try: event.setDropAction(Qt.Qt.CopyAction) except Exception as e: print(e) event.accept() else: event.ignore() def dropEvent(self, event): try: if event.mimeData().hasUrls: event.setDropAction(Qt.Qt.CopyAction) event.accept() links = [] for url in event.mimeData().urls(): links.append(str(url.toLocalFile())) print(links) else: event.ignore() except Exception as e: print(e)```
PYQT5(十九)标题栏如何隐藏放大缩小按钮,固定窗口大小
self.window.setWindowFlags(QtCore.Qt.WindowTitleHint|QtCore.Qt.WindowCloseButtonHint) --------------------- 固定窗口大小 self.window.setFixedSize(100,200)
PYQT5(二十) 设置窗口小图标和标题
from PyQt5 import QtCore, QtGui#相关库 . . .#这里省略中间的一些代码 _translate = QtCore.QCoreApplication.translate self.window.setWindowIco(QIcon('./test.jgp')) self.window.setWindowTitle(_translate("window", "CLIENT INFO")) self.window.setWindowFlags(QtCore.Qt.WindowTitleHint|QtCore.Qt.WindowCloseButtonHint)#隐藏关闭按钮
PYQT5(二十一)设置窗口位置
self.window.move(500,500)
PYQT5(二十二)Qlabel边框和背景颜色
self.setFrameShape(QFrame.Box) self.setStyleSheet('border-width: 1px;border-style: solid; border-color: rgb(255, 170, 0);background-color: rgb(100,149,237);') print('dialog_label')
PYQT5(二十三)FOCUS焦点事件
self.setFocusPolicy(QtCore.Qt.ClickFocus) def focusInEvent(self, QFocusEvent): print('focus in') pix = QPixmap('icon/action2.png') self.setPixmap(pix) def focusOutEvent(self, QFocusEvent): pix = QPixmap('icon/123.png') self.setPixmap(pix) ---------------------- https://www.jianshu.com/p/ef674f39499d
PYQT5(二十四)文本框回应回车事件
self.sendLineEdit.returnPressed.connect(self.SendData)
这个是LineEdit按下Enter按键触发SendData函数
PYQT5(二十五) QLabel自适应
让QLabel自适应text的大小,直接用下面的代码: LabelName->adjustSize(); 让QLabel能够自动判断并换行显示: LabelName->setGeometry(QRect(328, 240, 329, 27*4)); //四倍行距 LabelName->setWordWrap(true); LabelName->setAlignment(Qt::AlignTop);
PYQT5(二十六)打开外部链接
def outer(self): QtGui.QDesktopServices.openUrl(QtCore.QUrl('http://www.hao123.com'))
PYQT5(二十七)输出log到文件中
with open('log','a+') as l: print("date.txt exits%s \n"%now, file=l)
PYQT5(二十八)文本框自动跟随文本多少改变大小
需要重写控件,我用的是QTextedit,其他的应该也是差不多的。 self.document().contentsChanged.connect(self.textAreaChanged) def textAreaChanged(self): #判断文本框长度变化 # self.document().adjustSize() newHeight = self.document().size().height() + 30 print(newHeight) if newHeight>300: self.setGeometry(QtCore.QRect(self.X, self.Y, 141, 300)) else: self.setGeometry(QtCore.QRect(self.X, self.Y, 141, newHeight)) self.setLineWrapMode(1)
PYQT5(二十九)多屏幕适配问题
self.move(int(QApplication.desktop().screenGeometry(0).width())-180, 90, ) # screenGeometry(0)就是主屏幕 # 1的话是分屏1,以此类推
PYQT5(三十)去掉窗口标题栏,去掉任务栏显示,窗口置顶的方法
this->setWindowFlags (Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint); // 去掉标题栏,去掉任务栏显示,窗口置顶 翻译成pyqt--------------------- window.setWindowFlags (Qt.Qt.FramelessWindowHint|Qt.Qt.WindowStaysOnTopHint|Qt.Qt.Tool)
PYQT5(三十一)保存窗口位置下次使用
from PyQt5.Qt import QMainWindow,QDialog import json window=QMainWindow() def save_location(self): with open('window_location.txt','w') as f: data={'x':self.window.x(),'y':self.window.y()} f.write(json.dumps(data)) def load_laction(self): with open('window_location.txt', 'r') as f: txt=f.read() print(txt) j=json.loads(txt) return j
PYQT5(三十二)QMainWindow 重写CloseEvent
def closeEvent(self, e): e.ignore() self.hide() self.save_location()
PYQT5(三十三)输入对话框
QID = QInputDialog() QID.setGeometry(int((screen.width() - size.width()) / 2), int((screen.height() - size.height())) / 2, 200, 200) text, ok = QID.getText(self.window, '输入', '标题')
PYQT5(三十四)日期控件
self.dateEdit.setDate(QDate.currentDate())
self.dateEdit.setCalendarPopup(True)
三十五 没啥用,作者的近况
PYQT5(三十六)获取屏幕分辨率大小
from PyQt5.QtWidgets import QApplication, QWidget self.desktop = QApplication.desktop() self.screenRect = self.desktop.screenGeometry() self.height = self.screenRect.height() self.width = self.screenRect.width()
PYQT5(三十七)表格控件调整列宽
列宽自动分配 -------------------------------------- self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) -------------------------------------- self.tableWidget.verticalHeader().setSectionResizeMode(QHeaderView.Stretch) -------------------------------------- 这个是行宽的 此种模式下,我们没法手动调整列宽。 手动调整 -------------------------------------- self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive) 固定值 -------------------------------------- self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed) 用户无法调整该部分的大小。该部分只能使用resizeSection()以编程方式调整大小。节大小默认为defaultSectionSize。 随内容分配列宽 -------------------------------------- self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.tableWidget.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents) 我们把它和列宽自动分配结合在一起看,效果立马显现。 上面两种方式结合 -------------------------------------- self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.tableWidget.horizontalHeader().setSectionResizeMode(0, QHeaderView.Interactive) 列宽是自动分配的,但是第一列我们可以手动调整宽度,而表格整体的列宽仍是自动分配的。第二、三列我们没有办法调整列宽,这个是自动分配的。 自定义列宽 -------------------------------------- 1. self.tableWidget.setColumnWidth(0, 40) 2. self.tableWidget.setColumnWidth(1, 200) 3. self.tableWidget.setColumnWidth(2, 200)
PYQT(三十八)PDF阅读器
https://blog.csdn.net/weixin_43773093/article/details/88783757 随便复制了一下,以防走丢。 UI 设计 首先使用 Qt Designer 设计出图形界面: 新建一个 MainWindow 主界面,然后设置一个 toolbar,并在 toolbar 中添加三个 action,并为每个 action 设置好相应图标。 也可以直接 compile 我制作好的 PyReader.ui 文件,或者导入 Ui_PyReader.py 文件。 依赖要求 Python3 PyQt5 PyMuPDF 主要任务 我们使用 PyMuPDF 来解析 PDF ,来获取 PDF 文本信息。 安装 我们只须在 cmd 中输入:pip install PyMuPDF,即可安装 PyMuPDF。 导入 导入 PyMuPDF import fitz 在本节中,我们只需了解以下几个基本操作: fitz.open() 函数用来读取 PDF 文件内容,doc.loadPage() 函数用来获取具体某一页的信息。特别的 ,我们使用loadPage(0) 来获取封面信息。 # 读取 PDF doc = fitz.open(fname) # 获取第 n 页内容 page = doc.loadPage(n) 本节主要的内容就是把封面渲染到主界面中,并完成添加与删除封面的任务。 显示表格 我们采用 QtWidgets.QTableWidget 表格控件来显示封面。 首先让我们设置表格样式与功能: 其中,我们设置了单元格的纵横比为 4 : 3,以及其他的一些静态属性,并将 self.table 与右键菜单绑定,支持点击单元格调用 self.generateMenu 函数。 ---------------------------------------------------- def _setTableStyle(self): # 开启水平与垂直滚轴 self.table.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) # 设置 5 行 8 列 的表格 self.table.setColumnCount(8) self.table.setRowCount(5) # 设置标准宽度 self.width = self.screen.width() // 8 # 设置单元格的宽度 for i in range(8): self.table.setColumnWidth(i, self.width) # 设置单元格的高度 # 设置纵横比为 4 : 3 for i in range(5): self.table.setRowHeight(i, self.width * 4 // 3) # 隐藏标题栏 self.table.verticalHeader().setVisible(False) self.table.horizontalHeader().setVisible(False) # 禁止编辑 self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) # 不显示网格线 self.table.setShowGrid(False) # 将单元格绑定右键菜单 # 点击单元格,调用 self.generateMenu 函数 self.table.setContextMenuPolicy(Qt.CustomContextMenu) self.table.customContextMenuRequested.connect(self.generateMenu) ---------------------------------------------------- 加封面 首先让我们来看如何生成 TableWidget 可显示的 图像类文件。 我们通过 doc.loadPage(0) 获取页面对象,并传递给 render_pdf_page() 函数,设置缩放比为 1 : 1。首先构建 QImage 对象,在通过 convertFromImage 函数将 QImage 对象转化为可显示对象。 ---------------------------------------------------- # 显示 PDF 封面 # page_data 为 page 对象 def render_pdf_page(page_data, for_cover=False): # 图像缩放比例 zoom_matrix = fitz.Matrix(4, 4) if for_cover: zoom_matrix = fitz.Matrix(1, 1) # 获取封面对应的 Pixmap 对象 # alpha 设置背景为白色 pagePixmap = page_data.getPixmap( matrix = zoom_matrix, alpha=False) # 获取 image 格式 imageFormat = QtGui.QImage.Format_RGB888 # 生成 QImage 对象 pageQImage = QtGui.QImage( pagePixmap.samples, pagePixmap.width, pagePixmap.height, pagePixmap.stride, imageFormat) # 生成 pixmap 对象 pixmap = QtGui.QPixmap() pixmap.convertFromImage(pageQImage) return pixmap ---------------------------------------------------- 接着,我们就要想单元格中添加封面图片: 我们使用工具栏中的 + 号来添加 PDF 封面。 ---------------------------------------------------- self.addbar.triggered.connect(self.open),当点击 + 号时,就会调用 self.open 函数。 ---------------------------------------------------- 我们通过 getOpenFileName() 函数 来获取文件地址,self 后面的三个参数分别是窗口名称,文件默认路径以及支持的文件类型,这个函数返回文件的地址。 filter_book() 函数用来确保不会重复显示同一本书的封面。 ---------------------------------------------------- def getfile(self): # 打开单个文件 fname, _ = QFileDialog.getOpenFileName(self, 'Open files', './', '(*.pdf)') return fname def open(self): # 打开文件 fname = self.getfile() if self.filter_book(fname): self.setIcon(fname) # 获取无重复图书的地址 def filter_book(self, fname): if not fname: return False if fname not in self.booklist: self.booklist.append(fname) return True return False ---------------------------------------------------- 然后,我们就要将 PDF 封面渲染到主界面上: label.setScaledContents(True) 使得图片可以充满 label。self.table.setCellWidget(self.x, self.y, label) 用来设置标签的行与列。最后确保每八个元素换行,换行后将列数清零。 ---------------------------------------------------- def setIcon(self, fname): # 打开 PDF doc = fitz.open(fname) # 加载封面 page = doc.loadPage(0) # 生成封面图像 cover = render_pdf_page(page, True) label = QLabel(self) # 设置图片自动填充 label label.setScaledContents(True) # 设置封面图片 label.setPixmap(QPixmap(cover)) # 设置单元格元素为 label self.table.setCellWidget(self.x, self.y, label) # 删除 label 对象,防止后期无法即时刷新界面 # 因为 label 的生存周期未结束 del label # 设置当前行数与列数 self.crow, self.ccol = self.x, self.y # 每 8 个元素换行 if (not self.y % 7) and (self.y): self.x += 1 self.y = 0 else: self.y += 1 ---------------------------------------------------- 右键菜单 上面我们已经提到,如何将单元格与右键菜单绑定。 本次教程中,右键菜单只有两项,分别为开始阅读(暂未实现),以及删除图书。 ---------------------------------------------------- def generateMenu(self, pos): row_num = col_num = -1 # 获取选中的单元格的行数以及列数 for i in self.table.selectionModel().selection().indexes(): row_num = i.row() col_num = i.column() # 若选取的单元格中有元素,则支持右键菜单 if (row_num < self.crow) or (row_num == self.crow and col_num <= self.ccol): menu = QMenu() # 添加选项 item1 = menu.addAction('开始阅读') item2 = menu.addAction('删除图书') # 获取选项 action = menu.exec_(self.table.mapToGlobal(pos)) if action == item1: pass # 点击选项二,调用 self.delete_book 删除图书 elif action == item2: self.delete_book(row_num, col_num) ---------------------------------------------------- 接下来,让我们看如何删除图书: 首先维护一个 self.booklist ,里面储存无重复 PDF 文件地址。首先获取图书在 booklist 中的索引,在 booklist 中删除该元素。接着清空选中单元格之后(包含选中单元格)的所有单元格的内容。最后将 booklist 中 index 之后的图书地址重新显示到 table 上。简单地说,就是删除选中单元格,并将之后单元格向前挪一位。 ---------------------------------------------------- # 删除图书 def delete_book(self, row, col): # 获取图书在列表中的位置 index = row * 8 + col self.x = row self.y = col if index >= 0: self.booklist.pop(index) i, j = row, col while 1: # 移除 i 行 j 列单元格的元素 self.table.removeCellWidget(i, j) # 一直删到最后一个有元素的单元格 if i == self.crow and j == self.ccol: break if (not j % 7) and j: i += 1 j = 0 else: j += 1 # 如果 booklist 为空,设置当前单元格为 -1 if not self.booklist: self.crow = -1 self.ccol = -1 # 删除图书后,重新按顺序显示封面图片 for fname in self.booklist[index:]: self.setIcon(fname) ----------------------------------------------------
PyQt5(三十九)QTableWidget(表单控件)自适应窗口大小、栏位大小调整及布局
https://blog.csdn.net/yl_best/article/details/84070231
PYQT5(四十)下载并安装配置QT-DESIGNER
https://www.jianshu.com/p/4df033879a3f
(1)找不着
PYQT5(2)MyScrollWidget拖放文件功能的实现
class MyScrollWidget(QWidget): def __init__(self): super(QWidget, self).__init__() # self.resize(800, 600) self.move(0, 0) # self.setMouseTracking(False) self.last_time_move = 0 self.last_time_move_x = 0 def eventFilter(self,source, event): try: if event.type() == QEvent.MouseMove: print(event.pos().y(),event.pos().x()) if self.last_time_move == 0: self.last_time_move = event.pos().y() self.last_time_move_x=event.pos().x() distance = (self.last_time_move - event.pos().y())/100 distance_x = (self.last_time_move - event.pos().x())/100 self.scroll(distance_x,0) self.last_time_move = event.pos().y() self.last_time_move_x=event.pos().x() elif event.type() == QEvent.MouseButtonRelease: self.last_time_move = 0 self.last_time_move_x = 0 return QWidget.eventFilter(self, source, event) except Exception as e: print(e) #by the way 没能搞定y轴上的滚动,不过发现用滚轮也可以,就先放一放了,实现功能再回来优化
PYQT5(3)多线程QProgressBar卡死的问题
def init_progress(parent): m = wake_progress() parent.progress = m m.run() if not m.window.isVisible(): m.window.show() #激活方法 class wake_progress(QThread): #线程类 def __init__(self): super().__init__() self.window = QMainWindow() self.p='' def run(self): self.p =file_upload_statu_bar(self.window) class file_upload_statu_bar(progress_bar): #原始类 def __init__(self,Form): print('progress bar') self.window=Form super().__init__() self.setupUi(Form) self.window.show() def change(self,name): self.label.setText(name)
出现进度条的线程卡死的情况
最后通过参考自知诸狭的文章
其中一段:
对于执行很耗时的程序来说,由于PyQt需要等待程序执行完毕才能进行下一步,这个过程表现在界面上就是卡顿;而如果在执行这个耗时程序时不断地运行QApplication.processEvents(),那么就可以实现一边执行耗时程序,一边刷新页面的功能,会给人一种相对更流畅的感觉,QApplication.processEvents()的使用方法是,在主函数执行耗时操作的地方,加入QApplication.processEvents(),processEvents()函数的使用方法简单来说就是刷新页面。
于是在循环内加入
from PyQt5.QtWidgets import QApplication def slotAdd(self): for n in range(10): str_n = 'File index {0}'.format(n) self.listFile.addItem(str_n) QApplication.processEvents()#这一句是关键 time.sleep(1)
就可以成功解决问题
PYQT5 (4)之QSystemTrayIcon实现窗口最小化到托盘
from PyQt5 import QtGui from PyQt5.QtWidgets import QSystemTrayIcon class MyTray(QSystemTrayIcon): def __init__(self): super().__init__() try: self.setIcon(QtGui.QIcon('icon/car.png')) self.activated.connect(self.iconClicked) except Exception as e: print(e) def bind(self,window): self.parent_window=window def test(self): try: self.parent_window.show() except Exception as e: print(e) def iconClicked(self,reason): #鼠标点击icon传递的信号会带有一个整形的值,1是表示单击右键,2是双击,3是单击左键,4是用鼠标中键点击" print('click') if reason == 2 :#2是双击 self.test()
加一段添加二级菜单的功能,暂未试验过
def showMenu(self): "设计托盘的菜单,这里我实现了一个二级菜单" self.menu = QMenu() self.menu1 = QMenu() self.showAction1 = QAction("显示消息1", self, triggered=self.showM) self.showAction2 = QAction("显示消息2", self,triggered=self.showM) self.quitAction = QAction("退出", self, triggered=self.quit) self.menu1.addAction(self.showAction1) self.menu1.addAction(self.showAction2) self.menu.addMenu(self.menu1, ) self.menu.addAction(self.showAction1) self.menu.addAction(self.showAction2) self.menu.addAction(self.quitAction) self.menu1.setTitle("二级菜单") self.setContextMenu(self.menu)
PYQT5(5)带跳转按钮的QTableWidgets
from PyQt5 import QtWidgets, QtCore from PyQt5.QtWidgets import QTableWidget, QTableWidgetItem class btn_table(QTableWidget): def __init__(self,x,y,window,res): self.centralwidget = QtWidgets.QWidget(window) self.centralwidget.setObjectName("centralwidget") self.centralwidget.resize(500,500) super().__init__(self.centralwidget) self.setGeometry(QtCore.QRect(20, 10, 471, 401)) self.setObjectName("client_table") self.setColumnCount(x) self.setRowCount(y) self.buttonForRow(res) self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) def buttonForRow(self,res):#添加内容并在最后一行添加一个按钮 # requir:[[value1,value2,value3,...],[value1,value2,value3,value4,...]] self.clear() for i in range(0,len(res)): try: item = self.horizontalHeaderItem(i) self.setHorizontalHeaderItem(i, item) except Exception as e: print(e) t = QtWidgets.QTableWidgetItem() self.setHorizontalHeaderItem(i, t) item = self.horizontalHeaderItem(i) for a in range(0,len(res[i])): self.setItem(i,a,QtWidgets.QTableWidgetItem(str(res[i][a]))) print(res[i][a]) # self.setItem(i, 1, QtWidgets.QTableWidgetItem(str(res[i][1]))) btn=self.GenerateBtn(res[i][1]) self.setCellWidget(i,len(res[0]),btn) def GenerateBtn(self,clientid): viewBtn = QtWidgets.QPushButton('查看') viewBtn.setStyleSheet(''' text-align : center; background-color : DarkSeaGreen; height : 30px; border-style: outset; color:white; font : 13px; ''') viewBtn.clicked.connect(lambda:self.jump(clientid) ) return viewBtn def jump(self,clientid): print(clientid)
大概效果如下
PYQT(6)python3.4+pymssql+pyinstaller 编译exe 出错问题
我用的是pyinstaller -F -w来生成单独的exe 文件,总是出现 缺少__mssql什么的文件 百度一下得出解决办法: http://www.tuicool.com/articles/7RbU3i 后来.py文件加了下面代码 import pymssql import _mssql _mssql.__version__ 使用pyinstaller打包的时候主要注意这几个包 requests pymssql
PYQT5(7)实现可以拖拽的窗体
class MyWindow(QMainWindow): def __init__(self): super().__init__() def mousePressEvent(self, event): if event.button() == Qt.Qt.LeftButton: self.m_flag = True self.m_Position = event.globalPos() - self.pos() # 获取鼠标相对窗口的位置 event.accept() self.setCursor(QCursor(Qt.Qt.OpenHandCursor)) # 更改鼠标图标 def mouseMoveEvent(self, QMouseEvent): if Qt.Qt.LeftButton and self.m_flag: self.move(QMouseEvent.globalPos() - self.m_Position) # 更改窗口位置 QMouseEvent.accept() def mouseReleaseEvent(self, QMouseEvent): self.m_flag = False self.setCursor(QCursor(Qt.Qt.ArrowCursor))
PYQT5(8)重写Qlabel
from PyQt5 import Qt, QtCore from PyQt5.QtWidgets import QLabel, QFrame class dialog_label(QLabel): def init(self,centralwidget): super().init(centralwidget) # self.dialog_label.setGeometry(QtCore.QRect(30, 30, 251, 91)) self.setFrameShape(QFrame.Box) self.setStyleSheet('border-width: 1px;border-style: solid;border-color: rgb(255, 170, 0);') print('dialog_label') 0人点赞 PYQT5进阶日志
PYQT5(9)QLabel 实现右键在点击位置弹出菜单,并绑定事件
class MyLabel(QLabel): def __init__(self,centralwidget): #centralwidget 窗体参数 super().__init__(centralwidget) self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.rightMenuShow)#开放右键策略 def rightMenuShow(self, point): #添加右键菜单 self.popMenu = QMenu() tj=QAction(u'添加', self) sc=QAction(u'删除', self) xg = QAction(u'修改', self) self.popMenu.addAction(tj) self.popMenu.addAction(sc) self.popMenu.addAction(xg) #绑定事件 tj.triggered.connect(self.test) sc.triggered.connect(self.test) xg.triggered.connect(self.test) self.showContextMenu(QtGui.QCursor.pos()) def test(self): print('test') def showContextMenu(self, pos): #调整位置 ''''' 右键点击时调用的函数 ''' # 菜单显示前,将它移动到鼠标点击的位置 self.popMenu.move( pos) self.popMenu.show()
PYQT5(10)Qlabel实现捕捉键盘按键事件
def keyPressEvent(self, event): if (event.key() == Qt.Qt.Key_P):#P if QApplication.keyboardModifiers() == Qt.Qt.ShiftModifier:#shirft print("shift + p") self.talk_edit.show() self.talk_edit.setFocus() else: print("p") print('okokok')
https://blog.csdn.net/m0_37828248/article/details/79766580?utm_source=blogxgwz8
PYQT5(11)自适应文字高宽的Qtextedit
self.width = 24 self.height = 42 self.edit.resize(self.width, self.height) self.document = self.edit.document() self.document.contentsChanged.connect(self.textAreaChanged) self.edit.setLineWrapMode(QTextEdit.NoWrap)
def textAreaChanged(self): self.document.adjustSize() newWidth = self.document.size().width() + 10 newHeight = self.document.size().height() + 20 if newWidth != self.edit.width(): self.edit.setFixedWidth(newWidth) if newHeight != self.edit.height(): self.edit.setFixedHeight(newHeight)
PYQT5(12)可复用的自动保存窗口位置的frame
import json import os from PyQt5.QtWidgets import QMainWindow class AutoSaveWindow(QMainWindow): def __init__(self,name=''): #注意初始化的时候要带上name参数 super().__init__() self.name=name if os.path.exists('window_location_%s.txt'%self.name): self.load_location() #每次启动都检查位置并移动 def closeEvent(self, *args, **kwargs): self.save_location() def save_location(self): with open('window_location_%s.txt'%self.name, 'w') as f: data = {'x': self.x(), 'y': self.y()} f.write(json.dumps(data)) def load_location(self): with open('window_location_%s.txt'%self.name, 'r') as f: txt = f.read() print(txt) j = json.loads(txt) self.move(j['x'],j['y'])
PYQT5(13)重复绑定按钮事件需要做的一件事情
btn.disconnect()
PYQT5(14)pyqt5 QTreeWidget使用集锦(如右键菜单)
比较好的教程:https://zhuanlan.zhihu.com/p/36033317
【简介】
PyQT5中 QTreeWidget 例子
from PyQt5.QtWidgets import * import sys class TreeWidgetDemo(QMainWindow): def **init**(self, parent=None): super(TreeWidgetDemo, self).**init**(parent) self.setWindowTitle('TreeWidget 例子') self.tree = QTreeWidget() # 设置列数 self.tree.setColumnCount(2) # 设置头的标题 self.tree.setHeaderLabels(['Key', 'Value']) # 设置自适应宽度 self.header().setSectionResizeMode(QHeaderView.ResizeToContents) root = QTreeWidgetItem(self.tree) root.setText(0, 'root') root.setText(1, '0') child1 = QTreeWidgetItem(root) child1.setText(0, 'child1') child1.setText(1, '1') child2 = QTreeWidgetItem(root) child2.setText(0, 'child2') child2.setText(1, '2') child3 = QTreeWidgetItem(root) child3.setText(0, 'child3') child3.setText(1, '3') child4 = QTreeWidgetItem(child3) child4.setText(0, 'child4') child4.setText(1, '4') child5 = QTreeWidgetItem(child3) child5.setText(0, 'child5') child5.setText(1, '5') self.tree.addTopLevelItem(root) self.tree.clicked.connect(self.onTreeClicked) self.setCentralWidget(self.tree) def onTreeClicked(self, qmodelindex): item = self.tree.currentItem() print("key=%s ,value=%s" % (item.text(0), item.text(1)))
启动一下试试
if **name** == '**main**': app = QApplication(sys.argv) tree = TreeWidgetDemo() tree.show() sys.exit(app.exec_())
分析判断是否是父项
def onTreeClicked(self, qmodelindex): item = self.tree.currentItem() if item.parent()==None: print("key=%s ,value=%s" % (item.text(0), item.text(1))) #None表示是最高一级
信号触发条件:
activated(QModelIndex) 当用户激活index指定的项目时,发出此信号 clicked(QModelIndex) 左键单击鼠标按钮时,发出此信号 collapsed(QModelIndex) 当索引指定的项目折叠时,发出信号。 currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)当前项目更改时,发出信号 doubleClicked(QModelIndex) 双击鼠标按钮时,发出此信号 entered(QModelIndex) 当鼠标光标进入index指定的项目时,发出此信号 expanded(QModeldelIndex) 当索引指定的项目展开时,发出信号 iconSizeChanged(QSize) 在视图可见时设置此图标大小时,发出此信号 itemActivated(QTreeWidgetItem*,int) 当用户通过单击,双击或按特殊键(例如,Enter)激活项目时,发出信号 itemChanged(QTreeWidgetItem*,int) 当指定项目中列的内容发生更改时,发出信号 itemClicked(QTreeWidgetItem*,int) 当用户在窗口内单击时,发出信号。 itemCollapsed(QTreeWidgetItem*) 折叠指定项目时,发出信号 itemDoubleClicked(QTreeWidgetItem*,int) 当用户在窗口内双击时,发出信号 itemEntered(QTreeWidgetItem*,int) 当鼠标光标进入指定列上的项目时,发出信号 itemExpanded(QTreeWidgetItem*) 扩展指定项目时,发出信号 itemPressed(QTreeWidgetItem*,int) 当用户在窗口内按下鼠标按钮时,发出信号。 itemSelectionChange() 当树构件中的选择发生变化时,发出信号 pressed(QModelIndex) 按下鼠标按钮时,发出信号 viewportEntered() 当鼠标光标进入控件时,发出信号
获取父项某一个column的内容和
def getLocation(self,item): if item.parent(): temp = item.parent().text(0) parent=self.getLocation(item.parent()) if parent : res=os.path.join(parent,temp) return res else: return temp else: return 0 #举例,text(0)是文件夹的名称,那么递归后就可以获取全部路径
右键菜单
def __init__(self): self.setContextMenuPolicy(Qt.CustomContextMenu)#打开右键菜单的策略 self.customContextMenuRequested.connect(self.rightClickMenu)#绑定事件 def rightClickMenu(self,pos): try: self.contextMenu = QMenu()#创建对象 self.actionA = self.contextMenu.addAction(u'动作')#添加动作 self.actionA = self.contextMenu.addAction(u'动作b') self.actionA.triggered.connect(self.actionHandler) self.contextMenu.exec_(self.mapToGlobal(pos))#随指针的位置显示菜单 self.contextMenu.show()#显示 except Exception as e: print(e) def actionHandler(self): print(self.currentItem().text(0))
删除子节点下的所有item
item=self.currentItem() for i in range(0,item.childCount()): print(item.child(item.childCount()-1).text(0)) item.removeChild(item.child(item.childCount()-1))