之前用python寫了個小軟件https://blog.51cto.com/ikezcn/2142638
說實話用tk的話界面確實不好看,所以需要改進(jìn),看了pyqt5的介紹想要試一下,對于上次寫的軟件來說這里只是更改了界面而已。上面的程序不再更新。
創(chuàng)新互聯(lián)建站10多年成都定制網(wǎng)站服務(wù);為您提供網(wǎng)站建設(shè),網(wǎng)站制作,網(wǎng)頁設(shè)計及高端網(wǎng)站定制服務(wù),成都定制網(wǎng)站及推廣,對混凝土泵車等多個行業(yè)擁有多年的網(wǎng)站設(shè)計經(jīng)驗的網(wǎng)站建設(shè)公司。
使用的軟件:
python3.6
pyqt5 安裝:pip insatll pyqt5
界面:
代碼(干貨來了,之后會不定時更新):
# -*- coding: utf-8 -*-
#v2.0 2018-08-30更新
#v2.1 2018-08-31更新
#現(xiàn)在可以使用pyinsatller打包了,新增了樣式表,就算沒有數(shù)據(jù)庫也會自己創(chuàng)建并增加數(shù)據(jù)表,隱藏列名
#v2.2 2018-09-05更新
#增加了左邊一列用來做查詢條件,雙擊就可以搜索.
#右鍵右邊的路徑可以添加搜索條件.
#最后遇到一個問題:多次使用setFilter會造成模型出現(xiàn)問題導(dǎo)致無法寫入數(shù)據(jù)庫,這里就直接跳過模型自己插入數(shù)據(jù)庫
#v2.3 2018-09-06更新
#增加刷新菜單,顯示所有路徑,修復(fù)bug
#v2.4 2018-09-11更新
#小修小補(bǔ)
import sys,os
from PyQt5 import sip
from PyQt5.QtCore import Qt,QVariant,QFile,QIODevice,QItemSelectionModel
from PyQt5.QtSql import QSqlDatabase,QSqlTableModel,QSqlQuery,QSqlRecord
from PyQt5.QtWidgets import QPushButton,QLabel,QCheckBox,QHBoxLayout,QVBoxLayout,QWidget,QMenu,QMainWindow,QMessageBox,QHeaderView,QAction, qApp, QApplication, QDesktopWidget , QGridLayout,QTableView,QAbstractItemView
from PyQt5.QtGui import QIcon,QContextMenuEvent
import win32api
import win32con
class 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():#如果沒有找到數(shù)據(jù)庫文件就自動創(chuàng)建
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,"數(shù)據(jù)表創(chuàng)建失敗",self.query.lastError().text())
self.query.prepare("CREATE TABLE cxtj(cxtj text not NULL)")
if not self.query.exec():
QMessageBox.information(self,"數(shù)據(jù)表創(chuàng)建失敗",self.query.lastError().text())
else:
QMessageBox.information(self,"程序?qū)㈥P(guān)閉",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("&整理數(shù)據(jù)庫", self)
vacuumAction.setShortcut("Ctrl+D")
vacuumAction.setStatusTip("讓數(shù)據(jù)庫變小")
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('&設(shè)置')
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提供了關(guān)于用戶桌面的信息,包括屏幕尺寸。
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) #點(diǎn)擊整行選中
#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) #點(diǎn)擊整行選中
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,"程序?qū)㈥P(guān)閉",self.sqlite.lastError().text())
sys.exit(app.exec_())
def contextMenuEvent(self,event): #右鍵菜單
popAction = QAction(self)
popAction.setText("創(chuàng)建搜索條件")
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()
# 遍歷輸出拖動進(jìn)來的所有文件路徑
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'取消選擇了{(lán)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'選擇了{(lán)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,"程序?qū)㈥P(guān)閉",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_())
數(shù)據(jù)庫 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); /*選中區(qū)域的背景色*/
font: bold 14px;
/*注釋*/
}
QMenuBar{
font: 14px;
}
QStatusBar{
font: 14px;
}
QT的樣式表使用起來確實很方便,按CSS做的很多地方都是一樣的,代碼里有qt官網(wǎng)的樣式表介紹連接
說說PYQT5與TK的使用感覺,TK上手方便,拿起來就能寫,PYQT5需要了解它的工作機(jī)制所以上手時間會比較長。比較喜歡qss、tableview、tablemodel,qss可以很方便的調(diào)整樣式而且和js很像,用過js的上手那叫一個快,tableview與tablemodel聯(lián)動可以少些很多代碼,最主要的它的容錯度很高,有些可以不用寫try也不會造成程序停止運(yùn)行,這點(diǎn)很重要,哈哈,重要的點(diǎn)就在于‘懶’。
程序打包之后可以直接修改stylesheet.qss,樣式一樣會改變好方便,可以做定制,贊。
新聞標(biāo)題:快捷方式管理(pyqt5升級版)附代碼純干貨pytq5p
文章來源:http://muchs.cn/article40/geddeo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供手機(jī)網(wǎng)站建設(shè)、微信小程序、面包屑導(dǎo)航、營銷型網(wǎng)站建設(shè)、做網(wǎng)站、建站公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)