电脑自带的图片浏览器,很好用,但不是万能的。现实中有各种特殊需求,因此有时为了方便,量身打造一款适合自己的图片浏览器可能是有必要的。各种特殊需求总是不一样的,我这儿的特殊需求就是:我有成百上千的图片需要查看,查看中当遇到特殊图片我需要把这张图片单独挑选出存放在一个文件夹下,然后进行下一张,重复这个过程挑选完这堆图片中所有特殊的图片存放在一个文件夹下。咋一看,你可能觉得这简单呀,何须自己弄个工具呀,你会怎么做?是 用电脑自带的图片浏览器一张张看,当遇到特殊问题图片,再把这张图片拎出来放在一个文件夹下,如果图片少这么做也是不错的选择,但是当图片比较多,而且你以后还会多次遇到这种情况,量身定制一款自己的图片浏览器是一个很不错的选择。下面就用PyQt5简单实现这一过程吧
我使用的是PyCharm作为IDE,因此首先的安装这个软件,然后配置PyQt5,designer,.ui文件转.py文件工具等,这些网上有比较多额资料,在此不做说明。下面使用视图说一下完成这个任务的流程。
1、打开PyCharm ,启动designer,完成如下界面的各个组件搭建
本任务只需要5个组件,其中4个为Push Button 按钮,用于鼠标点击触发事件,1个Label控件用于显示图像;各个组件的一些属性设置可以在右侧查看修改,在此不细说。各个组件的名字最好重命名为和操作事件相关的字符,我的命名如上图右上边所示。这些在后续代码也要使用。
2、界面布局
组件创建设置属性好了以后,根据最终界面的形式,我把界面整体布局为水平布局,左侧为功能区按钮,右侧为图像显示区域;而左侧功能各个组件需要垂直布局一下;为了整个组件和界面随主窗体有缩放性,最后还需要整体布局一下。下面按布局的顺序一一说明一下。
2.1 按钮区域布局(竖直布局)
具体操作:先选中需要布局的这四个组件-----》右键单击,选中Lay out -----》选择竖直布局
2.2 按钮区和图像显示区域布局
具体操作:先选中2.1已经布局好的单击按钮组合和图像显示区Label组件-----》右键单击,选中Lay out -----》选择水平布局
经过上述操作后,形成的视图如下:
现在的界面看着很不好看,但没关系的,继续后面操作。
2.3 整体布局
具体操作:在非含有上述几个组件的区域-----》右键单击,选中Lay out -----》选择水平布局或竖直布局,的到的界面乳腺如下:
从图上可以看到按钮组合区域和图像显示区域平分水平区域,这样看着不美观,进行下面的调整就可。
2.4 水平布局比例调整
找到界面上的Objext Inspector 下的HorizontalLayout,选中它,在其下方的Property Editor找到layoutStretch,看到了原始的为0,0,我现在把他改为1,8,调整的示例和改后的界面如上图所示。
到现在为止界面的整体就算完成了,执行Ctr+R,得到如下图所示:
3 ui文件转化为py文件
实现ui文件转化为py文件需要安装工具,在此假设安装了。具体在此不叙述。回到PyCharm主界面,选中刚才的ui文件---》右键,找到External Tools---》PyUIC(这个是我的ui文件转py文件工具名),单击它就会在PyCharm工程目录下出现了和ui文件同名的py文件。这个过程也来一张截图吧直观。
在此把这个原始的py文件代码也贴在这里吧
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ScanImTool.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# 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(1193, 747)
font = QtGui.QFont()
font.setPointSize(12)
font.setBold(False)
font.setWeight(50)
MainWindow.setFont(font)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.centralwidget)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.OpenDirBnt = QtWidgets.QPushButton(self.centralwidget)
font = QtGui.QFont()
font.setPointSize(20)
font.setBold(True)
font.setWeight(75)
self.OpenDirBnt.setFont(font)
self.OpenDirBnt.setIconSize(QtCore.QSize(20, 20))
self.OpenDirBnt.setObjectName("OpenDirBnt")
self.verticalLayout.addWidget(self.OpenDirBnt)
self.PreImBnt = QtWidgets.QPushButton(self.centralwidget)
font = QtGui.QFont()
font.setPointSize(20)
font.setBold(True)
font.setWeight(75)
self.PreImBnt.setFont(font)
self.PreImBnt.setObjectName("PreImBnt")
self.verticalLayout.addWidget(self.PreImBnt)
self.NextImBnt = QtWidgets.QPushButton(self.centralwidget)
font = QtGui.QFont()
font.setPointSize(20)
font.setBold(True)
font.setWeight(75)
self.NextImBnt.setFont(font)
self.NextImBnt.setObjectName("NextImBnt")
self.verticalLayout.addWidget(self.NextImBnt)
self.CopyCurImBnt = QtWidgets.QPushButton(self.centralwidget)
font = QtGui.QFont()
font.setPointSize(15)
font.setBold(False)
font.setItalic(False)
font.setUnderline(False)
font.setWeight(50)
font.setStrikeOut(False)
font.setKerning(True)
self.CopyCurImBnt.setFont(font)
self.CopyCurImBnt.setStyleSheet("background-color: rgb(255, 0, 0);")
self.CopyCurImBnt.setFlat(False)
self.CopyCurImBnt.setObjectName("CopyCurImBnt")
self.verticalLayout.addWidget(self.CopyCurImBnt)
self.horizontalLayout.addLayout(self.verticalLayout)
self.ImShowLabel = QtWidgets.QLabel(self.centralwidget)
self.ImShowLabel.setStyleSheet("background-color: rgb(255, 255, 255);")
self.ImShowLabel.setText("")
self.ImShowLabel.setObjectName("ImShowLabel")
self.horizontalLayout.addWidget(self.ImShowLabel)
self.horizontalLayout.setStretch(0, 1)
self.horizontalLayout.setStretch(1, 8)
self.horizontalLayout_2.addLayout(self.horizontalLayout)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1193, 26))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "图片查看器"))
MainWindow.setToolTip(_translate("MainWindow", "<html><head/><body><p>t</p></body></html>"))
self.OpenDirBnt.setText(_translate("MainWindow", "打开目录"))
self.PreImBnt.setText(_translate("MainWindow", "上一张图"))
self.NextImBnt.setText(_translate("MainWindow", "下一张图"))
self.CopyCurImBnt.setText(_translate("MainWindow", "拷贝当前图"))
self.ImShowLabel.setToolTip(_translate("MainWindow", "Image Show Region"))
这个py文件就是刚才ui界面的代码表达形式,这个原始py文件是不能直接运行的,需要添加一些回调函数和主函数才能运行起来的。
4、功能区回调函数的实现
看了代码就知道原始文件是不能直接运行的,没有main函数呀,但即使加了也没啥意义,因为你点击那些按钮也不给你执行什么功能,因此我们需要在上述代码中添加一些函数来完成这些功能。由于前面已经说得比较详细,而且代码也觉得还算简洁,故直接贴上不用过多解释了,有些python的知识一看就懂了。
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ScanImTool.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!
##2019/05/12 by DQ
from PyQt5 import QtCore, QtGui, QtWidgets
##########################################
import sys,os
import datetime
import shutil
CurFolder=os.getcwd()
DefaultImFolder=CurFolder
NowTime=datetime.datetime.now()
Month=str(NowTime.month).zfill(2)
Day=str(NowTime.day).zfill(2)
Hour=str(NowTime.hour).zfill(2)
Minute=str(NowTime.minute).zfill(2)
##########################################
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1193, 747)
font = QtGui.QFont()
font.setPointSize(12)
font.setBold(False)
font.setWeight(50)
MainWindow.setFont(font)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.centralwidget)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.OpenDirBnt = QtWidgets.QPushButton(self.centralwidget)
font = QtGui.QFont()
font.setPointSize(20)
font.setBold(True)
font.setWeight(75)
self.OpenDirBnt.setFont(font)
self.OpenDirBnt.setIconSize(QtCore.QSize(20, 20))
self.OpenDirBnt.setObjectName("OpenDirBnt")
self.verticalLayout.addWidget(self.OpenDirBnt)
self.PreImBnt = QtWidgets.QPushButton(self.centralwidget)
font = QtGui.QFont()
font.setPointSize(20)
font.setBold(True)
font.setWeight(75)
self.PreImBnt.setFont(font)
self.PreImBnt.setObjectName("PreImBnt")
self.verticalLayout.addWidget(self.PreImBnt)
self.NextImBnt = QtWidgets.QPushButton(self.centralwidget)
font = QtGui.QFont()
font.setPointSize(20)
font.setBold(True)
font.setWeight(75)
self.NextImBnt.setFont(font)
self.NextImBnt.setObjectName("NextImBnt")
self.verticalLayout.addWidget(self.NextImBnt)
self.CopyCurImBnt = QtWidgets.QPushButton(self.centralwidget)
font = QtGui.QFont()
font.setPointSize(15)
font.setBold(False)
font.setItalic(False)
font.setUnderline(False)
font.setWeight(50)
font.setStrikeOut(False)
font.setKerning(True)
self.CopyCurImBnt.setFont(font)
self.CopyCurImBnt.setStyleSheet("background-color: rgb(255, 0, 0);")
self.CopyCurImBnt.setFlat(False)
self.CopyCurImBnt.setObjectName("CopyCurImBnt")
self.verticalLayout.addWidget(self.CopyCurImBnt)
self.horizontalLayout.addLayout(self.verticalLayout)
self.ImShowLabel = QtWidgets.QLabel(self.centralwidget)
self.ImShowLabel.setStyleSheet("background-color: rgb(255, 255, 255);")
self.ImShowLabel.setText("")
self.ImShowLabel.setObjectName("ImShowLabel")
self.horizontalLayout.addWidget(self.ImShowLabel)
self.horizontalLayout.setStretch(0, 1)
self.horizontalLayout.setStretch(1, 8)
self.horizontalLayout_2.addLayout(self.horizontalLayout)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1193, 26))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
################定义相关变量并初始化################
self.ImFolder = '' #图片文件夹路径
self.ImNameSet = [] #图片集合
self.CurImId = 0 #当前显示图在集合中的编号
self.CopyImFolder = '' #Copy图片存放的文件夹
self.MainWindow = MainWindow
################button按钮点击事件回调函数################
self.OpenDirBnt.clicked.connect(self.OpenDirBntClicked)
self.NextImBnt.clicked.connect(self.NextImBntClicked)
self.PreImBnt.clicked.connect(self.PreImBntClicked)
self.CopyCurImBnt.clicked.connect(self.CopyCurImBntClicked)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "图片查看器"))
MainWindow.setToolTip(_translate("MainWindow", "<html><head/><body><p>t</p></body></html>"))
self.OpenDirBnt.setText(_translate("MainWindow", "打开目录"))
self.PreImBnt.setText(_translate("MainWindow", "上一张图"))
self.NextImBnt.setText(_translate("MainWindow", "下一张图"))
self.CopyCurImBnt.setText(_translate("MainWindow", "拷贝当前图"))
self.ImShowLabel.setToolTip(_translate("MainWindow", "Image Show Region"))
#########选择图片文件夹#########
def OpenDirBntClicked(self):
ImFolder = QtWidgets.QFileDialog.getExistingDirectory(None,"select folder", DefaultImFolder)#这个语句有些邪门
if ImFolder!='':
ImNameSet = os.listdir(ImFolder)
ImNameSet.sort()
ImPath = os.path.join(ImFolder, ImNameSet[0])
pix = QtGui.QPixmap(ImPath)
self.ImShowLabel.setPixmap(pix)
self.ImFolder=ImFolder
self.ImNameSet=ImNameSet
self.CurImId=0
_,SelectFolderName=os.path.split(ImFolder)
CopyImFolderName = 'From{}CopyIm_{}-{}-{}-{}'.format(SelectFolderName, Month, Day, Hour, Minute)
self.CopyImFolder = os.path.join(CurFolder, CopyImFolderName)
_translate = QtCore.QCoreApplication.translate
CurWinTitle = "看图工具1.0 " +\
" " +\
SelectFolderName+'\\'+ImNameSet[0]
self.MainWindow.setWindowTitle(_translate("MainWindow", CurWinTitle))
else:
print('请重新选择文件夹')
#########显示下一张图片 #########
def NextImBntClicked(self):
ImFolder=self.ImFolder
ImNameSet = self.ImNameSet
CurImId = self.CurImId
ImNum = len(ImNameSet)
if CurImId<ImNum-1:#不可循环看图
ImPath = os.path.join(ImFolder, ImNameSet[CurImId+1])
pix = QtGui.QPixmap(ImPath)
self.ImShowLabel.setPixmap(pix)
self.CurImId = CurImId+1
_, SelectFolderName = os.path.split(ImFolder)
_translate = QtCore.QCoreApplication.translate
CurWinTitle = "看图工具1.0 " + \
" " + \
SelectFolderName + '\\' + ImNameSet[CurImId+1]
self.MainWindow.setWindowTitle(_translate("MainWindow", CurWinTitle))
#########显示前一张图片 #########
def PreImBntClicked(self):
ImFolder = self.ImFolder
ImNameSet = self.ImNameSet
CurImId = self.CurImId
ImNum = len(ImNameSet)
if CurImId>0:#第一张图片没有前一张
ImPath = os.path.join(ImFolder, ImNameSet[CurImId -1])
pix = QtGui.QPixmap(ImPath)
self.ImShowLabel.setPixmap(pix)
self.CurImId = CurImId -1
_, SelectFolderName = os.path.split(ImFolder)
_translate = QtCore.QCoreApplication.translate
CurWinTitle = "看图工具1.0 " + \
" " + \
SelectFolderName + '\\' + ImNameSet[CurImId -1]
self.MainWindow.setWindowTitle(_translate("MainWindow", CurWinTitle))
if self.CurImId<0:
self.CurImId=0
#########copy 当前图片函数 #########
def CopyCurImBntClicked(self):
ImFolder = self.ImFolder
ImNameSet = self.ImNameSet
CurImId = self.CurImId
ImPath = os.path.join(ImFolder, ImNameSet[CurImId])
CopyImFolder=self.CopyImFolder
if not os.path.isdir(CopyImFolder):
os.makedirs(CopyImFolder)
shutil.copy(ImPath,CopyImFolder)
#########主函数入口 #########
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
mainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(mainWindow)
mainWindow.show()
sys.exit(app.exec_())
现在运行一下这个程序,找一些图片放置在一个文件夹下,试试看这个程序达到最初设想的功能了吗?如果你觉得这样使用这个工具每次在pycharm中启动不是很爽,那就执行第5步把它编译成exe文件,我想放哪里用就放哪里用。
5、py文件打包成exe文件
要实现这个功能,需要安装一个打包python程序未exe的库:pyinstaller,这个库的安装在此也不叙述。假设已经安装。如此的话,首先切换到cmd命令行,然后在其下执行:pyinstaller.exe -F -w E:\CodeProject\PythonProject\ViewImGUI\ScanImTool.py
其过程如图:
不要问我这条语句的具体解释我也是粘贴网上的。执行完上述命令,过会就会在adminstor某个文件夹下得到exe文件,具体在那个文件可以从最终的编译终端显示得到,如下图(这张图接上面的图,显示信息太多,上面的那张图截屏不下):
找到红色区域的位置,这个exe文件就在那里。好了现在你可以想放哪里用就放哪里用。
最后把这个小工具拿来试试,下面截取了两张图:
我把整个工程文件以及示例图片一并打包放置在这里:https://download.csdn.net/download/lingyunxianhe/11422828
积分本来想设置为1的,但自己不能设置了,就这样吧
啊这个过程还是有些小长。终于写完了。有些特别小的细节没有说明,但那都不重要了,有点python和qt基本知识的应该都一看就能懂得。