当前位置:   article > 正文

快捷方式管理(pyqt5升级版)附代码纯干货 pytq5 python3.6.0-32

python qt event.mimedata().hasurls()

之前用python写了个小软件https://blog.51cto.com/ikezcn/2142638
说实话用tk的话界面确实不好看,所以需要改进,看了pyqt5的介绍想要试一下,对于上次写的软件来说这里只是更改了界面而已。上面的程序不再更新。

使用的软件:
python3.6
pyqt5 安装:pip insatll pyqt5

界面:
快捷方式管理(pyqt5升级版)附代码纯干货 pytq5 python3.6.0-32
快捷方式管理(pyqt5升级版)附代码纯干货 pytq5 python3.6.0-32

代码(干货来了,之后会不定时更新):

  1. # -*- coding: utf-8 -*-
  2. #v2.0 2018-08-30更新
  3. #v2.1 2018-08-31更新
  4. #现在可以使用pyinsatller打包了,新增了样式表,就算没有数据库也会自己创建并增加数据表,隐藏列名
  5. #v2.2 2018-09-05更新
  6. #增加了左边一列用来做查询条件,双击就可以搜索.
  7. #右键右边的路径可以添加搜索条件.
  8. #最后遇到一个问题:多次使用setFilter会造成模型出现问题导致无法写入数据库,这里就直接跳过模型自己插入数据库
  9. #v2.3 2018-09-06更新
  10. #增加刷新菜单,显示所有路径,修复bug
  11. #v2.4 2018-09-11更新
  12. #小修小补
  13. import sys,os
  14. from PyQt5 import sip
  15. from PyQt5.QtCore import Qt,QVariant,QFile,QIODevice,QItemSelectionModel
  16. from PyQt5.QtSql import QSqlDatabase,QSqlTableModel,QSqlQuery,QSqlRecord
  17. from PyQt5.QtWidgets import QPushButton,QLabel,QCheckBox,QHBoxLayout,QVBoxLayout,QWidget,QMenu,QMainWindow,QMessageBox,QHeaderView,QAction, qApp, QApplication, QDesktopWidget , QGridLayout,QTableView,QAbstractItemView
  18. from PyQt5.QtGui import QIcon,QContextMenuEvent
  19. import win32api
  20. import win32con
  21. class Icon(QMainWindow):
  22. def __init__(self,model,sqlite,query,view,sview,smodel):
  23. super().__init__()
  24. self.model = model
  25. self.sqlite = sqlite
  26. self.query = query
  27. self.view = view
  28. self.sview = sview
  29. self.smodel = smodel
  30. if self.sqlite.open():#如果没有找到数据库文件就自动创建
  31. self.query.exec("select count(*) from sqlite_master where type='table' and name='lj'")
  32. if self.query.next():
  33. if self.query.value(0) == 0:
  34. self.query.prepare("CREATE TABLE lj(id integer primary key,lj text not NULL,isdel BOOLEAN DEFAULT 0)")
  35. if not self.query.exec():
  36. QMessageBox.information(self,"数据表创建失败",self.query.lastError().text())
  37. self.query.prepare("CREATE TABLE cxtj(cxtj text not NULL)")
  38. if not self.query.exec():
  39. QMessageBox.information(self,"数据表创建失败",self.query.lastError().text())
  40. else:
  41. QMessageBox.information(self,"程序将关闭",self.sqlite.lastError().text())
  42. sys.exit(app.exec_())
  43. self.setAcceptDrops(True)
  44. self.statusBar().showMessage('Reday')
  45. delAction = QAction("&删除", self)
  46. delAction.setShortcut("Ctrl+D")
  47. delAction.setStatusTip("删除选定的行")
  48. delAction.triggered.connect(self.delrow)
  49. deltableAction = QAction("&全部删除", self)
  50. deltableAction.setStatusTip("删除所有的行")
  51. deltableAction.triggered.connect(self.deltable)
  52. vacuumAction = QAction("&整理数据库", self)
  53. vacuumAction.setShortcut("Ctrl+D")
  54. vacuumAction.setStatusTip("让数据库变小")
  55. vacuumAction.triggered.connect(self.vacuum)
  56. selectAction = QAction("&刷新", self)
  57. selectAction.setShortcut("Ctrl+R")
  58. selectAction.setStatusTip("显示所有路径")
  59. selectAction.triggered.connect(self.selectAll)
  60. menubar = self.menuBar()
  61. menubar.addAction(delAction)
  62. setMenu = menubar.addMenu('&设置')
  63. setMenu.addAction(vacuumAction)
  64. setMenu.addAction(deltableAction)
  65. menubar.addAction(selectAction)
  66. widget = QWidget()
  67. QMainWindow.setCentralWidget(self,widget)
  68. layout = QHBoxLayout(self) #QHBoxLayout水平排列
  69. layout.addWidget(self.sview)
  70. layout.addWidget(self.view)
  71. layout.setStretchFactor(self.sview,1) #显示的比例 1:3
  72. layout.setStretchFactor(self.view,3)
  73. self.table1()
  74. self.stable()
  75. widget.setLayout(layout)
  76. self.resize(800, 600)
  77. self.center() #居中
  78. self.setWindowTitle("快捷方式")
  79. #self.setWindowIcon(QIcon("icon.png"))
  80. self.show()
  81. def selectAll(self):
  82. self.model.setFilter("1=1")
  83. def delrow(self):
  84. if self.view.selectionModel().hasSelection():
  85. self.query.prepare("delete from lj where lj=?")
  86. self.query.bindValue(0,QVariant(self.view.currentIndex().data()))
  87. if self.query.exec():
  88. self.model.setFilter("1=1")
  89. else:
  90. QMessageBox.information(self,"删除错误",self.model.lastError().text())
  91. if self.sview.selectionModel().hasSelection():
  92. self.query.prepare("delete from cxtj where cxtj=?")
  93. self.query.bindValue(0,QVariant(self.sview.currentIndex().data()))
  94. if self.query.exec():
  95. self.smodel.setFilter("1=1")
  96. else:
  97. QMessageBox.information(self,"删除错误",self.smodel.lastError().text())
  98. def deltable(self):
  99. ret = QMessageBox.question(self,"提示!","是否删除全部路径",QMessageBox.Ok | QMessageBox.Cancel,QMessageBox.Cancel)
  100. if 0x00000400 == ret: #OK
  101. self.query.prepare("delete from lj")
  102. if not self.query.exec():
  103. QMessageBox.information(self,"删除错误",self.model.lastError().text())
  104. self.query.prepare("delete from cxtj")
  105. if not self.query.exec():
  106. QMessageBox.information(self,"删除错误",self.smodel.lastError().text())
  107. def vacuum(self):
  108. self.query.exec("VACUUM")
  109. def center(self): #窗口居中
  110. #QtGui.QDesktopWidget提供了关于用户桌面的信息,包括屏幕尺寸。
  111. qr = self.frameGeometry()
  112. cp = QDesktopWidget().availableGeometry().center()
  113. qr.moveCenter(cp)
  114. self.move(qr.topLeft())
  115. def sql(self):
  116. sqlite = QSqlDatabase.addDatabase("QSQLITE")
  117. sqlite.setDatabaseName("db")
  118. return sqlite
  119. def table1(self):
  120. self.model.setTable("lj")
  121. #self.model.setFilter("isdel = 0") #where 条件
  122. self.model.setSort(1,Qt.AscendingOrder) #按lj列排序
  123. self.model.select()
  124. #self.model.setHeaderData(0, Qt.Horizontal, "ID")
  125. #self.model.setHeaderData(1, Qt.Horizontal,"路径")
  126. self.view.setModel(self.model)
  127. self.view.setEditTriggers(QAbstractItemView.NoEditTriggers) #禁止对表格编辑
  128. self.view.horizontalHeader().setStretchLastSection(True) #是否填满宽度
  129. self.view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
  130. self.view.hideColumn(0)#隐藏列
  131. self.view.hideColumn(2)#隐藏列
  132. self.view.setSelectionBehavior(QAbstractItemView.SelectRows) #点击整行选中
  133. #self.view.setAlternatingRowColors(True) #隔行自动变色
  134. self.view.verticalHeader().setVisible(False)#隐藏表头
  135. self.view.horizontalHeader().setVisible(False)#隐藏列名
  136. self.view.doubleClicked.connect(lambda:self.slotRowDoubleClicked())
  137. self.view.clicked.connect(lambda:self.singleSelect(view))
  138. #view.setAcceptDrops(True)
  139. self.view.show()
  140. def slotRowDoubleClicked(self):
  141. try:
  142. modedata = self.view.currentIndex().data()
  143. win32api.ShellExecute(0,'open',str(modedata),'','',1)
  144. except (BaseException):
  145. QMessageBox.information(self,"错误!","路径不存在!")
  146. def stable(self):
  147. self.smodel.setTable("cxtj")
  148. #self.model.setFilter("isdel = 0") #where 条件
  149. self.smodel.setSort(0,Qt.AscendingOrder) #按cxtj列排序
  150. self.smodel.setHeaderData(0, Qt.Horizontal,"搜索条件")
  151. self.smodel.select()
  152. self.sview.setModel(self.smodel)
  153. self.sview.setEditTriggers(QAbstractItemView.NoEditTriggers) #禁止对表格编辑
  154. self.sview.horizontalHeader().setStretchLastSection(True) #是否填满宽度
  155. self.sview.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
  156. self.sview.setSelectionBehavior(QAbstractItemView.SelectRows) #点击整行选中
  157. self.sview.verticalHeader().setVisible(False)#隐藏表头
  158. self.sview.horizontalHeader().setVisible(False)#隐藏列名
  159. self.sview.doubleClicked.connect(lambda:self.slotRowDoubleClickedS())
  160. self.sview.clicked.connect(lambda:self.singleSelect(sview))
  161. self.sview.show()
  162. def slotRowDoubleClickedS(self):
  163. modedata = self.sview.currentIndex().data()
  164. data = str(modedata)
  165. if self.sqlite.open():
  166. self.model.setFilter("lj like '%" + data + "%'") #where 条件
  167. else:
  168. QMessageBox.information(self,"程序将关闭",self.sqlite.lastError().text())
  169. sys.exit(app.exec_())
  170. def contextMenuEvent(self,event): #右键菜单
  171. popAction = QAction(self)
  172. popAction.setText("创建搜索条件")
  173. popAction.triggered.connect(self.popMenu)
  174. popMenubar = QMenu(self)
  175. popMenubar.addAction(popAction)
  176. popMenubar.exec(self.cursor().pos())
  177. def popMenu(self):
  178. i = 0
  179. sdata = []
  180. modedata = self.view.currentIndex().data()
  181. data = str(modedata)
  182. for txt in data.split("\\"):
  183. sdata.append((i,txt))
  184. i = i + 1
  185. self.cbWindow = cbWindow(sdata,self.sqlite,self.query,self.smodel)
  186. # def enableBorder(self, enable):
  187. # if enable:
  188. # self.setStyleSheet("MainWidget{border:3px solid #165E23}")
  189. # else:
  190. # self.setStyleSheet('')
  191. def dragEnterEvent(self, event):
  192. if event.mimeData().hasUrls():
  193. event.acceptProposedAction()
  194. #self.enableBorder(True)
  195. else:
  196. event.ignore()
  197. def dragMoveEvent(self, event):
  198. if event.mimeData().hasUrls():
  199. event.setDropAction(Qt.LinkAction)
  200. event.accept()
  201. else:
  202. event.ignore()
  203. #def dragLeaveEvent(self, event):
  204. #print('dragLeaveEvent...')
  205. #self.enableBorder(False)
  206. def dropEvent(self, event):
  207. #self.model.setFilter("1=1")
  208. if event.mimeData().hasUrls():
  209. counts = -1
  210. #record = self.model.record()
  211. # 遍历输出拖动进来的所有文件路径
  212. for url in event.mimeData().urls():
  213. self.query.prepare("select count(*) as c from lj where lj=?") #不加 as c会报错
  214. pathStr = url.toLocalFile().replace('/','\\')
  215. self.query.bindValue(0,QVariant(pathStr))
  216. if self.query.exec():
  217. while self.query.next():
  218. counts = self.query.value(0)
  219. if counts > 0:
  220. QMessageBox.information(self,"已存在!",pathStr)
  221. elif counts == 0:
  222. #record.setValue(1,QVariant(pathStr)) #lj列
  223. #record.setValue(2,QVariant(0)) #isdel列
  224. #self.model.insertRecord(-1,record)
  225. self.query.prepare("insert into lj(lj) values(?)")
  226. self.query.bindValue(0,QVariant(pathStr))
  227. self.query.exec()
  228. elif counts == -1:
  229. return
  230. event.acceptProposedAction()
  231. self.model.setFilter("1=1")
  232. #print(self.model.lastError().text())
  233. else:
  234. event.ignore()
  235. def singleSelect(self,lstView):
  236. if lstView == self.view:
  237. if self.sview.selectionModel().hasSelection():
  238. self.sview.selectionModel().clearSelection()
  239. if lstView == self.sview:
  240. if self.view.selectionModel().hasSelection():
  241. self.view.selectionModel().clearSelection()
  242. # for lstViewI in lstViews:
  243. # if lstViewI == lstView:
  244. # continue
  245. # # the check is necessary to prevent recursions...
  246. # if lstViewI.selectionModel().hasSelection():
  247. # # ...as this causes emission of selectionChanged() signal as well:
  248. # lstViewI.selectionModel().clearSelection()
  249. def closeEvent(self,event):
  250. if self.sqlite.isOpen():
  251. self.sqlite.close()
  252. self.close()
  253. class cbWindow(QWidget):
  254. def __init__(self,sdata,sqlite,query,smodel):
  255. super().__init__()
  256. self.sdata = sdata
  257. self.sqlite = sqlite
  258. self.query = query
  259. self.smodel = smodel
  260. self.cbStr = []
  261. layout = QVBoxLayout()
  262. #items = [(0, 'Python'), (1, 'Golang'), (2, 'JavaScript'), (3, 'Ruby')]
  263. for id_, txt in self.sdata:
  264. checkBox = QCheckBox(txt, self)
  265. checkBox.id_ = id_
  266. checkBox.stateChanged.connect(self.checkLanguage) #1
  267. layout.addWidget(checkBox)
  268. self.lMessage = QLabel(self)
  269. layout.addWidget(self.lMessage)
  270. self.button1 = QPushButton("保存",self)
  271. self.button1.clicked.connect(self.checkbutton1)
  272. layout.addWidget(self.button1)
  273. self.setLayout(layout)
  274. self.setWindowTitle("选择搜索条件")
  275. self.resize(200, 300)
  276. self.show()
  277. def checkLanguage(self, state):
  278. checkBox = self.sender()
  279. if state == Qt.Unchecked:
  280. self.cbStr.remove((checkBox.id_, checkBox.text()))
  281. #print(self.cbStr)
  282. #self.lMessage.setText(u'取消选择了{0}: {1}'.format(checkBox.id_, checkBox.text()))
  283. elif state == Qt.Checked:
  284. self.cbStr.append((checkBox.id_, checkBox.text()))
  285. #print(self.cbStr)
  286. #self.lMessage.setText(u'选择了{0}: {1}'.format(checkBox.id_, checkBox.text()))
  287. def checkbutton1(self):
  288. counts = -1
  289. if self.sqlite.isOpen():
  290. for id_, txt in self.cbStr:
  291. self.query.prepare("select count(*) as c from cxtj where cxtj=?")
  292. self.query.bindValue(0,QVariant(txt))
  293. if self.query.exec():
  294. while query.next():
  295. counts = query.value(0)
  296. if counts == 0:
  297. self.query.prepare("insert into cxtj(cxtj) values(?)")
  298. self.query.bindValue(0,QVariant(txt))
  299. if self.query.exec():
  300. self.smodel.setFilter("1=1")
  301. else:
  302. QMessageBox.information(self,"查询条件写入错误","查询条件写入错误")
  303. self.close()
  304. else:
  305. QMessageBox.information(self,"程序将关闭",self.sqlite.lastError().text())
  306. sys.exit(app.exec_())
  307. def closeEvent(self,event):
  308. self.close()
  309. if __name__ == "__main__":
  310. app = QApplication(sys.argv)
  311. qss = QFile("stylesheet.qss") #样式表
  312. qss.open(QIODevice.ReadOnly) #样式表
  313. app.setStyleSheet(str(qss.readAll(),encoding='utf-8')) #样式表
  314. #样式表 http://doc.qt.io/qt-5/stylesheet-customizing.html
  315. #样式表 http://doc.qt.io/qt-5/stylesheet-reference.html (QTableView stylesheet)
  316. qss.close() #样式表
  317. sqlite = QSqlDatabase.addDatabase("QSQLITE")
  318. sqlite.setDatabaseName("db")
  319. model = QSqlTableModel(None,sqlite)
  320. model.setEditStrategy(QSqlTableModel.OnManualSubmit)
  321. smodel = QSqlTableModel(None,sqlite)
  322. smodel.setEditStrategy(QSqlTableModel.OnManualSubmit)
  323. query = QSqlQuery(sqlite)
  324. view = QTableView()
  325. #view.setSelectionMode(QTableView.SingleSelection)
  326. sview = QTableView()
  327. #view.setSelectionMode(QTableView.SingleSelection)
  328. icon = Icon(model,sqlite,query,view,sview,smodel)
  329. sys.exit(app.exec_())

数据库 db

  1. CREATE TABLE lj(id integer primary key,lj text not NULL,isdel BOOLEAN DEFAULT 0)
  2. CREATE TABLE cxtj(cxtj text not NULL)

qss样式表 stylesheet.qss

  1. QTableView {
  2. gridline-color: white;
  3. selection-background-color: rgb(74,112,139); /*选中区域的背景色*/
  4. font: bold 14px;
  5. /*注释*/
  6. }
  7. QMenuBar{
  8. font: 14px;
  9. }
  10. QStatusBar{
  11. font: 14px;
  12. }

QT的样式表使用起来确实很方便,按CSS做的很多地方都是一样的,代码里有qt官网的样式表介绍连接

说说PYQT5与TK的使用感觉,TK上手方便,拿起来就能写,PYQT5需要了解它的工作机制所以上手时间会比较长。比较喜欢qss、tableview、tablemodel,qss可以很方便的调整样式而且和js很像,用过js的上手那叫一个快,tableview与tablemodel联动可以少些很多代码,最主要的它的容错度很高,有些可以不用写try也不会造成程序停止运行,这点很重要,哈哈,重要的点就在于‘懒’。

程序打包之后可以直接修改stylesheet.qss,样式一样会改变好方便,可以做定制,赞。

转载于:https://blog.51cto.com/ikezcn/2166426

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/264628
推荐阅读
相关标签
  

闽ICP备14008679号