快捷方式管理(pyqt5升级版)附代码纯干货 pytq5 p
发表于:2024-11-23 作者:千家信息网编辑
千家信息网最后更新 2024年11月23日,之前用python写了个小软件https://blog.51cto.com/ikezcn/2142638说实话用tk的话界面确实不好看,所以需要改进,看了pyqt5的介绍想要试一下,对于上次写的软件来
千家信息网最后更新 2024年11月23日快捷方式管理(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安全错误
数据库的锁怎样保障安全
安徽宣城软件开发培训怎么样
便宜的服务器平台
网络安全专业做什么工作好
号码数据库下载
数据库 image类型
幼儿网络安全图片卡通
网络安全主题班会开头
美国服务器抗投诉
邯郸软件开发公司图标
怀旧服服务器经验
数据库课件百度云
网络安全教育知识内容
网络安全事件回顾
怎么上公司服务器下载文件
大数据还需要存数据库吗
上海综合软件开发参考价格
安装复印机提示没有打印服务器
网络安全扫描抓包
游戏一个服务器多少钱
你们用的那个数据库连接池
仙桃订制软件开发中心
学校网络安全教学视频
web服务器登录请求
易保网络技术上海
碰一碰支付软件开发
群晖USB打印服务器
一般纳税人 软件开发税
网络安全视频软件
海南特色软件开发平均价格
QQ群机器人服务器永久