快捷方式管理(pyqt5升级版)附代码纯干货 pytq5 p
发表于:2025-02-19 作者:千家信息网编辑
千家信息网最后更新 2025年02月19日,之前用python写了个小软件https://blog.51cto.com/ikezcn/2142638说实话用tk的话界面确实不好看,所以需要改进,看了pyqt5的介绍想要试一下,对于上次写的软件来
千家信息网最后更新 2025年02月19日快捷方式管理(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安全错误
数据库的锁怎样保障安全
顺义区口碑好的网络技术服务介绍
服务器集群和云
安卓应用软件开发客户
票房数据库技术入股
苹果手机的服务器是什么
论文数据库字段名查重不
数据库任务平台
网络技术公司融资目的
数据库中true是什么意思
网络安全方面的实操视频
彭州网络安全法活动
重型网络技术产业化
网络安全中小学
服务器内存与普通内存区别
腾讯网络安全是谁负责的
湖北数据库
河南税控盘服务器云空间
南宁系统软件开发公司
mysql中的数据库模式
面试不会数据库怎么办呢
国际互联网科技博览会
服务器黑客攻击报警
杭州智能边缘计算服务器销售价格
软件开发招0基础吗
美国网络安全技术趋势
七匹狼软件开发
数据库违反实体完整性怎么报错
数据库设计 e-r图
服务器cpu模块怎么拔出来
涉密软件开发保密室清单