快捷方式管理(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安全错误
数据库的锁怎样保障安全
软件开发框架指的是什么
最好的网络技术论坛
服务器管理员我的世界
为什么嗨喽单车总是骑出服务器
计算机网络技术可能适合职业
熟练软件开发
山东图腾网络技术有限公司
数据库实例名xml配置
s助手 程序数据库
服务器改了端口登录不了
如何查询服务器当前时间
征文网络安全伴我行
08服务器怎么管理
开启远程服务器的任务管理器
苹果提高网络安全吗
自己做的服务器如何用手机浏览
2019电力行业网络安全
IP数据库技术学院
计算机网络技术的背景及意义
做软件开发需要哪些职位
软件开发可以办个体营业执照吗
支行开展金融网络安全演练
服务器bmc工程师主要工作
安装科密刷卡机没数据库怎么办
fm数据库五星
数据库中如何绑定规则
浙江发展网络技术咨询口碑推荐
软件开发岗位年终总结
zimg图片服务器
学校服务器的搞笑图片