快捷方式管理(pyqt5升级版)附代码纯干货 pytq5 p
发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,之前用python写了个小软件https://blog.51cto.com/ikezcn/2142638说实话用tk的话界面确实不好看,所以需要改进,看了pyqt5的介绍想要试一下,对于上次写的软件来
千家信息网最后更新 2025年12月02日快捷方式管理(pyqt5升级版)附代码纯干货 pytq5 p
之前用python写了个小软件https://blog.51cto.com/ikezcn/2142638
说实话用tk的话界面确实不好看,所以需要改进,看了pyqt5的介绍想要试一下,对于上次写的软件来说这里只是更改了界面而已。上面的程序不再更新。
使用的软件:
python3.6
pyqt5 安装:pip insatll pyqt5
界面:

代码(干货来了,之后会不定时更新):
# -*- coding: utf-8 -*-#v2.0 2018-08-30更新#v2.1 2018-08-31更新#现在可以使用pyinsatller打包了,新增了样式表,就算没有数据库也会自己创建并增加数据表,隐藏列名#v2.2 2018-09-05更新#增加了左边一列用来做查询条件,双击就可以搜索.#右键右边的路径可以添加搜索条件.#最后遇到一个问题:多次使用setFilter会造成模型出现问题导致无法写入数据库,这里就直接跳过模型自己插入数据库#v2.3 2018-09-06更新#增加刷新菜单,显示所有路径,修复bug#v2.4 2018-09-11更新#小修小补import sys,osfrom PyQt5 import sipfrom PyQt5.QtCore import Qt,QVariant,QFile,QIODevice,QItemSelectionModelfrom PyQt5.QtSql import QSqlDatabase,QSqlTableModel,QSqlQuery,QSqlRecordfrom PyQt5.QtWidgets import QPushButton,QLabel,QCheckBox,QHBoxLayout,QVBoxLayout,QWidget,QMenu,QMainWindow,QMessageBox,QHeaderView,QAction, qApp, QApplication, QDesktopWidget , QGridLayout,QTableView,QAbstractItemViewfrom PyQt5.QtGui import QIcon,QContextMenuEventimport win32apiimport win32conclass Icon(QMainWindow): def __init__(self,model,sqlite,query,view,sview,smodel): super().__init__() self.model = model self.sqlite = sqlite self.query = query self.view = view self.sview = sview self.smodel = smodel if self.sqlite.open():#如果没有找到数据库文件就自动创建 self.query.exec("select count(*) from sqlite_master where type='table' and name='lj'") if self.query.next(): if self.query.value(0) == 0: self.query.prepare("CREATE TABLE lj(id integer primary key,lj text not NULL,isdel BOOLEAN DEFAULT 0)") if not self.query.exec(): QMessageBox.information(self,"数据表创建失败",self.query.lastError().text()) self.query.prepare("CREATE TABLE cxtj(cxtj text not NULL)") if not self.query.exec(): QMessageBox.information(self,"数据表创建失败",self.query.lastError().text()) else: QMessageBox.information(self,"程序将关闭",self.sqlite.lastError().text()) sys.exit(app.exec_()) self.setAcceptDrops(True) self.statusBar().showMessage('Reday') delAction = QAction("&删除", self) delAction.setShortcut("Ctrl+D") delAction.setStatusTip("删除选定的行") delAction.triggered.connect(self.delrow) deltableAction = QAction("&全部删除", self) deltableAction.setStatusTip("删除所有的行") deltableAction.triggered.connect(self.deltable) vacuumAction = QAction("&整理数据库", self) vacuumAction.setShortcut("Ctrl+D") vacuumAction.setStatusTip("让数据库变小") vacuumAction.triggered.connect(self.vacuum) selectAction = QAction("&刷新", self) selectAction.setShortcut("Ctrl+R") selectAction.setStatusTip("显示所有路径") selectAction.triggered.connect(self.selectAll) menubar = self.menuBar() menubar.addAction(delAction) setMenu = menubar.addMenu('&设置') setMenu.addAction(vacuumAction) setMenu.addAction(deltableAction) menubar.addAction(selectAction) widget = QWidget() QMainWindow.setCentralWidget(self,widget) layout = QHBoxLayout(self) #QHBoxLayout水平排列 layout.addWidget(self.sview) layout.addWidget(self.view) layout.setStretchFactor(self.sview,1) #显示的比例 1:3 layout.setStretchFactor(self.view,3) self.table1() self.stable() widget.setLayout(layout) self.resize(800, 600) self.center() #居中 self.setWindowTitle("快捷方式") #self.setWindowIcon(QIcon("icon.png")) self.show() def selectAll(self): self.model.setFilter("1=1") def delrow(self): if self.view.selectionModel().hasSelection(): self.query.prepare("delete from lj where lj=?") self.query.bindValue(0,QVariant(self.view.currentIndex().data())) if self.query.exec(): self.model.setFilter("1=1") else: QMessageBox.information(self,"删除错误",self.model.lastError().text()) if self.sview.selectionModel().hasSelection(): self.query.prepare("delete from cxtj where cxtj=?") self.query.bindValue(0,QVariant(self.sview.currentIndex().data())) if self.query.exec(): self.smodel.setFilter("1=1") else: QMessageBox.information(self,"删除错误",self.smodel.lastError().text()) def deltable(self): ret = QMessageBox.question(self,"提示!","是否删除全部路径",QMessageBox.Ok | QMessageBox.Cancel,QMessageBox.Cancel) if 0x00000400 == ret: #OK self.query.prepare("delete from lj") if not self.query.exec(): QMessageBox.information(self,"删除错误",self.model.lastError().text()) self.query.prepare("delete from cxtj") if not self.query.exec(): QMessageBox.information(self,"删除错误",self.smodel.lastError().text()) def vacuum(self): self.query.exec("VACUUM") def center(self): #窗口居中 #QtGui.QDesktopWidget提供了关于用户桌面的信息,包括屏幕尺寸。 qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def sql(self): sqlite = QSqlDatabase.addDatabase("QSQLITE") sqlite.setDatabaseName("db") return sqlite def table1(self): self.model.setTable("lj") #self.model.setFilter("isdel = 0") #where 条件 self.model.setSort(1,Qt.AscendingOrder) #按lj列排序 self.model.select() #self.model.setHeaderData(0, Qt.Horizontal, "ID") #self.model.setHeaderData(1, Qt.Horizontal,"路径") self.view.setModel(self.model) self.view.setEditTriggers(QAbstractItemView.NoEditTriggers) #禁止对表格编辑 self.view.horizontalHeader().setStretchLastSection(True) #是否填满宽度 self.view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.view.hideColumn(0)#隐藏列 self.view.hideColumn(2)#隐藏列 self.view.setSelectionBehavior(QAbstractItemView.SelectRows) #点击整行选中 #self.view.setAlternatingRowColors(True) #隔行自动变色 self.view.verticalHeader().setVisible(False)#隐藏表头 self.view.horizontalHeader().setVisible(False)#隐藏列名 self.view.doubleClicked.connect(lambda:self.slotRowDoubleClicked()) self.view.clicked.connect(lambda:self.singleSelect(view)) #view.setAcceptDrops(True) self.view.show() def slotRowDoubleClicked(self): try: modedata = self.view.currentIndex().data() win32api.ShellExecute(0,'open',str(modedata),'','',1) except (BaseException): QMessageBox.information(self,"错误!","路径不存在!") def stable(self): self.smodel.setTable("cxtj") #self.model.setFilter("isdel = 0") #where 条件 self.smodel.setSort(0,Qt.AscendingOrder) #按cxtj列排序 self.smodel.setHeaderData(0, Qt.Horizontal,"搜索条件") self.smodel.select() self.sview.setModel(self.smodel) self.sview.setEditTriggers(QAbstractItemView.NoEditTriggers) #禁止对表格编辑 self.sview.horizontalHeader().setStretchLastSection(True) #是否填满宽度 self.sview.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.sview.setSelectionBehavior(QAbstractItemView.SelectRows) #点击整行选中 self.sview.verticalHeader().setVisible(False)#隐藏表头 self.sview.horizontalHeader().setVisible(False)#隐藏列名 self.sview.doubleClicked.connect(lambda:self.slotRowDoubleClickedS()) self.sview.clicked.connect(lambda:self.singleSelect(sview)) self.sview.show() def slotRowDoubleClickedS(self): modedata = self.sview.currentIndex().data() data = str(modedata) if self.sqlite.open(): self.model.setFilter("lj like '%" + data + "%'") #where 条件 else: QMessageBox.information(self,"程序将关闭",self.sqlite.lastError().text()) sys.exit(app.exec_()) def contextMenuEvent(self,event): #右键菜单 popAction = QAction(self) popAction.setText("创建搜索条件") popAction.triggered.connect(self.popMenu) popMenubar = QMenu(self) popMenubar.addAction(popAction) popMenubar.exec(self.cursor().pos()) def popMenu(self): i = 0 sdata = [] modedata = self.view.currentIndex().data() data = str(modedata) for txt in data.split("\\"): sdata.append((i,txt)) i = i + 1 self.cbWindow = cbWindow(sdata,self.sqlite,self.query,self.smodel) # def enableBorder(self, enable): # if enable: # self.setStyleSheet("MainWidget{border:3px solid #165E23}") # else: # self.setStyleSheet('') def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.acceptProposedAction() #self.enableBorder(True) else: event.ignore() def dragMoveEvent(self, event): if event.mimeData().hasUrls(): event.setDropAction(Qt.LinkAction) event.accept() else: event.ignore() #def dragLeaveEvent(self, event): #print('dragLeaveEvent...') #self.enableBorder(False) def dropEvent(self, event): #self.model.setFilter("1=1") if event.mimeData().hasUrls(): counts = -1 #record = self.model.record() # 遍历输出拖动进来的所有文件路径 for url in event.mimeData().urls(): self.query.prepare("select count(*) as c from lj where lj=?") #不加 as c会报错 pathStr = url.toLocalFile().replace('/','\\') self.query.bindValue(0,QVariant(pathStr)) if self.query.exec(): while self.query.next(): counts = self.query.value(0) if counts > 0: QMessageBox.information(self,"已存在!",pathStr) elif counts == 0: #record.setValue(1,QVariant(pathStr)) #lj列 #record.setValue(2,QVariant(0)) #isdel列 #self.model.insertRecord(-1,record) self.query.prepare("insert into lj(lj) values(?)") self.query.bindValue(0,QVariant(pathStr)) self.query.exec() elif counts == -1: return event.acceptProposedAction() self.model.setFilter("1=1") #print(self.model.lastError().text()) else: event.ignore() def singleSelect(self,lstView): if lstView == self.view: if self.sview.selectionModel().hasSelection(): self.sview.selectionModel().clearSelection() if lstView == self.sview: if self.view.selectionModel().hasSelection(): self.view.selectionModel().clearSelection() # for lstViewI in lstViews: # if lstViewI == lstView: # continue # # the check is necessary to prevent recursions... # if lstViewI.selectionModel().hasSelection(): # # ...as this causes emission of selectionChanged() signal as well: # lstViewI.selectionModel().clearSelection() def closeEvent(self,event): if self.sqlite.isOpen(): self.sqlite.close() self.close()class cbWindow(QWidget): def __init__(self,sdata,sqlite,query,smodel): super().__init__() self.sdata = sdata self.sqlite = sqlite self.query = query self.smodel = smodel self.cbStr = [] layout = QVBoxLayout() #items = [(0, 'Python'), (1, 'Golang'), (2, 'JavaScript'), (3, 'Ruby')] for id_, txt in self.sdata: checkBox = QCheckBox(txt, self) checkBox.id_ = id_ checkBox.stateChanged.connect(self.checkLanguage) #1 layout.addWidget(checkBox) self.lMessage = QLabel(self) layout.addWidget(self.lMessage) self.button1 = QPushButton("保存",self) self.button1.clicked.connect(self.checkbutton1) layout.addWidget(self.button1) self.setLayout(layout) self.setWindowTitle("选择搜索条件") self.resize(200, 300) self.show() def checkLanguage(self, state): checkBox = self.sender() if state == Qt.Unchecked: self.cbStr.remove((checkBox.id_, checkBox.text())) #print(self.cbStr) #self.lMessage.setText(u'取消选择了{0}: {1}'.format(checkBox.id_, checkBox.text())) elif state == Qt.Checked: self.cbStr.append((checkBox.id_, checkBox.text())) #print(self.cbStr) #self.lMessage.setText(u'选择了{0}: {1}'.format(checkBox.id_, checkBox.text())) def checkbutton1(self): counts = -1 if self.sqlite.isOpen(): for id_, txt in self.cbStr: self.query.prepare("select count(*) as c from cxtj where cxtj=?") self.query.bindValue(0,QVariant(txt)) if self.query.exec(): while query.next(): counts = query.value(0) if counts == 0: self.query.prepare("insert into cxtj(cxtj) values(?)") self.query.bindValue(0,QVariant(txt)) if self.query.exec(): self.smodel.setFilter("1=1") else: QMessageBox.information(self,"查询条件写入错误","查询条件写入错误") self.close() else: QMessageBox.information(self,"程序将关闭",self.sqlite.lastError().text()) sys.exit(app.exec_()) def closeEvent(self,event): self.close()if __name__ == "__main__": app = QApplication(sys.argv) qss = QFile("stylesheet.qss") #样式表 qss.open(QIODevice.ReadOnly) #样式表 app.setStyleSheet(str(qss.readAll(),encoding='utf-8')) #样式表 #样式表 http://doc.qt.io/qt-5/stylesheet-customizing.html #样式表 http://doc.qt.io/qt-5/stylesheet-reference.html (QTableView stylesheet) qss.close() #样式表 sqlite = QSqlDatabase.addDatabase("QSQLITE") sqlite.setDatabaseName("db") model = QSqlTableModel(None,sqlite) model.setEditStrategy(QSqlTableModel.OnManualSubmit) smodel = QSqlTableModel(None,sqlite) smodel.setEditStrategy(QSqlTableModel.OnManualSubmit) query = QSqlQuery(sqlite) view = QTableView() #view.setSelectionMode(QTableView.SingleSelection) sview = QTableView() #view.setSelectionMode(QTableView.SingleSelection) icon = Icon(model,sqlite,query,view,sview,smodel) sys.exit(app.exec_())数据库 db
CREATE TABLE lj(id integer primary key,lj text not NULL,isdel BOOLEAN DEFAULT 0)CREATE TABLE cxtj(cxtj text not NULL)qss样式表 stylesheet.qss
QTableView {gridline-color: white;selection-background-color: rgb(74,112,139); /*选中区域的背景色*/font: bold 14px;/*注释*/}QMenuBar{font: 14px;}QStatusBar{font: 14px;}QT的样式表使用起来确实很方便,按CSS做的很多地方都是一样的,代码里有qt官网的样式表介绍连接
说说PYQT5与TK的使用感觉,TK上手方便,拿起来就能写,PYQT5需要了解它的工作机制所以上手时间会比较长。比较喜欢qss、tableview、tablemodel,qss可以很方便的调整样式而且和js很像,用过js的上手那叫一个快,tableview与tablemodel联动可以少些很多代码,最主要的它的容错度很高,有些可以不用写try也不会造成程序停止运行,这点很重要,哈哈,重要的点就在于'懒'。
程序打包之后可以直接修改stylesheet.qss,样式一样会改变好方便,可以做定制,赞。
样式
数据
条件
数据库
路径
错误
更新
程序
搜索
代码
数据表
界面
软件
查询
选择
重要
宽度
文件
模型
菜单
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
网络安全的电影书籍
新能源汽车电池软件开发
网络安全等级保护技术咨询
公安网络安全漏洞
数据库怎么批量增加数据
数据库专业技术岗位
sci数据库检索三种方式
apex更新后服务器卡
数据库上市公司生意宝
清远保洁行业软件开发有哪些
甲基化位点在线数据库
天翼1号本机网络安全吗
金融公司融资信息基础数据库
敏捷软件开发方法的出现
船舶系统组态软件开发
杭州源锦网络技术有限公司
小学网络安全舆情监测制度
架设内网穿透服务器
普及网络安全知识的黑板报
数据库 录像档案 录著
数据库质检
互联网科技人工智能时代
楚送网络技术工作室
ip中国代理服务器
各类数据库的文献检索功能和特点
mysql数据库设计案例
杭州 网络技术有限公司
单人舞视频软件开发
阿里云数据库密码重置
直播交友软件开发