一、工作中,有一个关键词查找工作,查找开发版本中使用的文本,有哪些词语是非法的,一个一个去查太累了,所以想到了用代码来实现。可后来想想,能否做成简单的小工具,大家都可以使用。
于是就着手编写工具。原来是计划用Python自带的lib库:tkinter,写的时候发现真不好操作,网上对应的说明文档也比较少。所以查找了好久,决定用PyQt5来实现。
二、大概思路:①.使用designer.exe绘制窗体;②使用eric6生成主窗口对应的py文件;③编辑调用主窗口的程序;④使用信号(signal)和槽(slot)机制建立窗体的动作指令;⑤调试打包
三、实现过程
1.PyQt5的安装上篇已做介绍,打开designer.exe,新建一个ui文件。如图,放置了3个QPushButton,然后放置了QLineEdit和QTextEdit,第一个设置了默认文本(placeholderText设置),保存为openfile.ui
2.在eric6中,先创建一个项目,在forms窗体,添加openfile.ui,然后编译,生成Ui_openfile.py,如下附录2中的代码
3.创建主程序openfile.py,导入界面程序:from Ui_openfile import *,然后再导入其他需要的库。
4.编写类class,定义其中关于界面点击的函数
类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。方法:类中定义的函数。
5.定义方法:findtxt,主要实现查找已有文本,是否在目标文件中。方法findtxt是一个槽函数,要与前面的信号关联起来。所以在前面的Ui_openfile.py,添加信号语句:self.button_find.clicked.connect(self.findtxt),这样信号和槽就关联起来了。
在获取目标文件时,需要打开一个文件选择框。此时定义了另一个函数:loadtxt,实现打开文件选择控件,获取文本内容,并把目标文件的路径写在下方的文本框里。使用方法:self.loadtxt()来调用类中的另一个函数,获取目标文件内容。
(另外:方法loadtxt也可以成为一个槽函数,要与前面的信号关联起来。可以在前面的Ui_openfile.py,添加信号语句:self.button_openfile.clicked.connect(self.loadtxt),进行信号和槽的关联)
当查找完毕后,可以在findtxt后面添加语句: self.lineEdit.setText('结果已保存在D盘list.txt文件')。这样就可以做到通知执行结果的作用。
6.同样的,定义方法:listappear。实现获取关键词文本内容并显示。然后在前面添加信号:self.button_keylist.clicked.connect(self.listappear),进行信号和槽函数的关联。
7.编写完毕后,检查无问题,CMD窗口执行语句:Python openfile.py ,会自动调用Ui_openfile.py,这样一个小工具就初步告成了。
8.编译打包。有多个py文件时,主文件放在前面即可,打包命令:C:UsersadminAppDataLocalProgramsPythonPython37Scripts>pyinstaller -F openfile.py Ui_openfile.py
打包后生成exe文件,打开是闪退,提示错误: ImportError: unable to find Qt5Core.dll on PATH
经过查找,参考博客 https://blog.csdn.net/zwyact/article/details/99778898 ,添加一小段代码后解决。
四.附录程序,注意缩进时,同一文本缩进方式要保持一致(TAB间缩进和四个空格缩进,只用一种)会省去编译报错的困扰:
报错信息:IndentationError: unexpected indent;IndentationError: expected an indented block
解决办法,可以用文本编辑器Notepad++把当前python脚本的所有空格或Tab字符都显示出来查看,视图 -> 显示符号 -> 显示空格与制表符,这样就能看到缩进方式了。
.主程序,很多异常都未写出来,后面逐步优化
import sys,os
if hasattr(sys, 'frozen'):
os.environ['PATH'] = sys._MEIPASS + ";" + os.environ['PATH']
from PyQt5.QtWidgets import *
from Ui_openfile import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
file='//19.87.8.11/testtools/keywords.txt'
class MyMainWindow(QMainWindow,Ui_mainWindow):
def __init__(self,parent=None):
super(MyMainWindow,self).__init__(parent)
self.setupUi(self)
def loadtxt(self): #打开文本选择路径框,获取目标文本
filename,_=QFileDialog.getOpenFileName(self,'open file','.','txt(*.txt)') #QFileDialog是用于打开和保存文件的标准对话框
def readtext(filename): #读取文本内容
fullText = []
textcon = open(filename, 'r', encoding='utf-8') #使用utf-8编码打开,非此编码的文本打开有问题,可以采用忽略错误的方式
for i in textcon:
lincone = i.strip()
fullText.append(lincone)
#print(fullText)
return '
'.join(fullText)
textcon.close()
if filename:
cur_path=QDir('.')
relative_path = cur_path.relativeFilePath(filename)
self.folderlist.setText(relative_path) #显示获取文本的路径
self.goal=readtext(filename)
def findtxt(self):
j=0
text_con=open(file, 'r', encoding='utf-8') #关键词所在的文本
self.loadtxt() #调用获取目标文本内容函数
goal_con=self.goal
for i in text_con:
line_cone = i.strip()
#print(line_cone)
j = j + 1
if line_cone in goal_con: #主程序中的关键程序,写了那么多,其他都是为了这个服务,南啊
f=open('d:/list.txt','a',encoding='utf-8')
f.write(str(j)+line_cone+'
')
self.lineEdit.setText('结果已保存在D盘list.txt文件') #结果提示
def listappear(self): #获取关键词文本内容,展示出来。
fullText = ''
textcon = open(file, 'r', encoding='utf-8')
for i in textcon:
lincone = i.strip()
fullText=fullText+lincone+','
self.keylist.setText(fullText) #设置的文本内容是个字符串,所以不能用前面的列表形式收集。
textcon.close()
if __name__=="__main__":
app=QApplication(sys.argv)
myWin=MyMainWindow()
myWin.show()
sys.exit(app.exec_())
2.ui文件
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'D:1.soft88.Python-Ericeric6worksecondwindow.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_mainWindow(object):
def setupUi(self, mainWindow):
mainWindow.setObjectName("mainWindow")
mainWindow.resize(662, 430)
self.centralwidget = QtWidgets.QWidget(mainWindow)
self.centralwidget.setObjectName("centralwidget")
self.button_keylist = QtWidgets.QPushButton(self.centralwidget)
self.button_keylist.setGeometry(QtCore.QRect(80, 160, 121, 41))
self.button_keylist.setObjectName("button_keylist")
self.keylist = QtWidgets.QTextEdit(self.centralwidget)
self.keylist.setGeometry(QtCore.QRect(230, 160, 251, 151))
self.keylist.setObjectName("keylist")
self.folderlist = QtWidgets.QLineEdit(self.centralwidget)
self.folderlist.setGeometry(QtCore.QRect(230, 100, 401, 31))
self.folderlist.setObjectName("folderlist")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(230, 40, 241, 31))
self.lineEdit.setObjectName("lineEdit")
self.button_find = QtWidgets.QPushButton(self.centralwidget)
self.button_find.setGeometry(QtCore.QRect(80, 40, 121, 31))
self.button_find.setObjectName("button_find")
self.button_openfile = QtWidgets.QPushButton(self.centralwidget)
self.button_openfile.setGeometry(QtCore.QRect(80, 100, 121, 31))
self.button_openfile.setObjectName("button_openfile")
mainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(mainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 662, 23))
self.menubar.setObjectName("menubar")
mainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(mainWindow)
self.statusbar.setObjectName("statusbar")
mainWindow.setStatusBar(self.statusbar)
self.retranslateUi(mainWindow)
self.button_find.clicked.connect(self.findtxt) #信号signal
self.button_keylist.clicked.connect(self.listappear) #信号signal
QtCore.QMetaObject.connectSlotsByName(mainWindow)
def retranslateUi(self, mainWindow):
_translate = QtCore.QCoreApplication.translate
mainWindow.setWindowTitle(_translate("mainWindow", "关键字查询V1.0"))
self.button_keylist.setText(_translate("mainWindow", "当前已有关键词"))
self.lineEdit.setPlaceholderText(_translate("mainWindow", "结果保存在D盘list文本文件"))
self.button_find.setText(_translate("mainWindow", "查找"))
self.button_openfile.setText(_translate("mainWindow", "目标文件路径"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
mainWindow = QtWidgets.QMainWindow()
ui = Ui_mainWindow()
ui.setupUi(mainWindow)
mainWindow.show()
sys.exit(app.exec_())