荒废博客多时,主要是平时太懒,写完的代码都存着电脑上,去写博客又浪费时间,但随着代码越来越多,我发现好多曾经学过的东西都忘了(毕竟写代码的时候懒得注释)所以,从现在起养成写博客的好习惯,好了,废话不多说,下面介绍一下第一个pyqt的程序。
pyqt和c++的qt基本没有差别,上次在做数据结构课设的时候学习了C++的qt,可是由于后来基本不怎么使用,现在差不多是忘得一干二尽了,因为现在主要是使用python语言,所以就转到pyqt上来了。
主要工具:
python 3.5
pyqt5
windows10
首先确定自己要干什么,因为最近想做一个人脸疲劳检测的东西,所以就想要做一个给数据打标签的东西,因为初学qt,所以做的比较简单。
第一步,导入所需要的类
from __future__ import division,print_function
import sys
from PyQt5.QtWidgets import QWidget,QLabel,QApplication,QMainWindow,qApp,QAction,QFileDialog
from PyQt5.QtWidgets import QPushButto,QDesktopWidget,QFrame,QScrollArea
from PyQt5.QtWidgets import QLabel,QLineEdit,QTextEdit,QGridLayout,QMessageBox
from PyQt5.QtCore import Qt,QRect
from PyQt5.QtGui import QPen,QPainter,QIcon,QImage,QPixmap
import glob
import os
至于上面的东西都是干嘛的,下面会有提到,接下来,我需要一个可以自己输入标签内容的button,这个东西当然是没有的,所以可以自己创造一个出来,代码如下:
class Button(QPushButton):
def __init__(self,title,parent = None,icon = None):
super().__init__(title,parent)
if icon:
self.setIcon(QIcon(icon))
self.setAcceptDrops(True)
def dragEnterEvent(self,e):
'''
给按钮添加的是否是text/plain内容,是就发生拖拽动作,不是就忽略
'''
if e.mimeData().hasFormat('text/plain'):
e.accept()
else:
e.ignore()
def dropEvent(self,e):
'''
将文字添加到标签上
'''
self.setText(e.mimeData().text())
下面,写一下显示图片的页面
class MainTools(QFrame):
def __init__(self,parent):
super().__init__(parent)
self.initUI()
def initUI(self):
self.initPushButton()
self.setAcceptDrops(True)
def initPushButton(self):
'''
将一个窗口部件采用网格布局,将按钮等添加上去
'''
grid = QGridLayout()
grid.setSpacing(10)#组件间隔
self.setLayout(grid)
self.sc = QScrollArea(self)#滑动布局
self.next = QPushButton("Next>>")
self.front = QPushButton('<
不得不说,只要开头工作做好了,下面写起来并不是很难,而且函数都可以看到名字就知道像网格布局,滑动窗口,另外说一句,每个部件都可以指定一个QWidget作为parent,其作用就是让他显示在该QWidget上,但是这样布局就失去意义了,一般就是将部件添加进布局,布局之间嵌套,然后将布局添加进QWidget。
接下来就是主窗口了。
class LabelTool(QMainWindow):
def __init__(self):
self.count = 0#当前读到图片数
self.succed = []已读图片
super().__init__()
self.initUI()
def initUI(self):
self.mt = MainTools(self)
self.setCentralWidget(self.mt)
self.initMenuBar()#下面几行都是信号和槽的连接,即点击按钮会发生的动作
self.mt.next.clicked.connect(self.nextImage)
self.mt.front.clicked.connect(self.frontImage)
self.mt.lab1.clicked.connect(self.lab)
self.mt.lab2.clicked.connect(self.lab2)
self.mt.lab3.clicked.connect(self.lab3)
self.mt.lab4.clicked.connect(self.lab4)
self.__screen__()#设置窗口尺寸
self.center()#中心化
self.setWindowTitle('Face Classfical Label')
self.show()
def __screen__(self):
screen = QDesktopWidget().screenGeometry()
self.resize(screen.width()/2,screen.height()/2)
def initMenuBar(self):#添加菜单栏的操作
file = QAction(QIcon("./Icon/file.png"),'&FileFolder',self)
exit = QAction(QIcon(None),'&Exit',self)
pen = QAction(QIcon("./Icon/pen.png"),'&Pen',self)
file.setShortcut('Crt+F')
exit.setShortcut('Crt+Q')
pen.setShortcut('Crt+P')
file.setStatusTip('打开文件夹')
exit.setStatusTip('退出程序')
pen.setStatusTip('画笔工具')#没有实现
file.triggered.connect(self.openFolder)
exit.triggered.connect(self.close)
self.statusBar()
menubar = self.menuBar()
filemenu = menubar.addMenu('&Floder')
filemenu.addAction(file)
penmenu = menubar.addMenu('&Pen')
penmenu.addAction(pen)
exitmenu = menubar.addMenu('&Exit')
exitmenu.addAction(exit)
def openFolder(self):#选择文件夹
self.count = 0
dir = QFileDialog.getExistingDirectory(self,'选取文件夹')#该函数可以直接请求文件夹
self.dir = dir
if self.dir:
self.load_dir()
else:
return
if len(self.file_list) > 0:
icon = QLabel()
if len(self.succed) == 0:
file = self.file_list[self.count]
else:
self.count = len(self.succed)
file = self.file_list[self.count]
icon.setPixmap(QPixmap(file))
self.mt.sc.setWidget(icon)
self.mt.text.setText("")
self.count += 1
else:
self.mt.text.setText('没有在该文件夹下找到图片')
def center(self):
screen = QDesktopWidget().screenGeometry()
size = self.geometry()
self.move((screen.width() - size.width())/2,
(screen.height() - size.height())/2)
def load_dir(self):#加载文件夹下的图片
extends = ['.jpg','.png','.jpeg']
sub_dir = [x[0] for x in os.walk(self.dir)]
if len(sub_dir) == 1:
base_name = ['']
else:
base_name = [os.path.basename(x) for x in sub_dir[1:]]
self.file_list = []
for name in base_name:
for extend in extends:
file_glob = os.path.join(self.dir,name,'*'+extend)
self.file_list.extend(glob.glob(file_glob))
path = os.path.join(self.dir,'item','items.txt')
if os.path.exists(path):
with open(path,'r') as f:
self.succed = [x.split(' ')[0] for x in f.readlines()]
def nextImage(self):#下一个图片
file = self.file_list[self.count - 1]
if self.count <= len(self.file_list) and file not in self.succed:
item = self.mt.text.toPlainText()
if len(item) > 0:
self.saveText(str(item))
self.succed.append(file)
if len(self.file_list) > self.count:
next_file = self.file_list[self.count]
self.mt.nextButton(next_file)
self.mt.text.setText('')
self.count += 1
def frontImage(self):#上一张图片
if self.count > 0:
self.count -= 1
file = self.file_list[self.count-1]
self.mt.nextButton(file)
def saveText(self,item):
path = os.path.join(self.dir,'item','items.txt')
if not os.path.exists(os.path.dirname(path)):
os.makedirs(os.path.dirname(path))
with open(path,'a+',encoding='utf-8') as wf:
for i in item:
wf.write(i)
wf.write('\n')
def lab(self):#打标签
if self.mt.sc.widget():
label = self.mt.lab1.text()
self.mt.text.setText(self.file_list[self.count-1]+" "+str(label))
def lab2(self):
if self.mt.sc.widget():
label = self.mt.lab2.text()
self.mt.text.setText(self.file_list[self.count-1]+" "+str(label))
def lab3(self):
if self.mt.sc.widget():
label = self.mt.lab3.text()
self.mt.text.setText(self.file_list[self.count-1]+" "+str(label))
def lab4(self):
if self.mt.sc.widget():
label = self.mt.lab4.text()
self.mt.text.setText(self.file_list[self.count-1]+" "+str(label))
上面就是全部的代码,功能比较简单,代码也不多,作为入门练手还是不错的,但是还是有一些逻辑上的bug没有修改,目前效果大概就是下面这样
我给打包成exe了根据的是PyQt5 Pyinstaller打包注意事项这篇文章,至于为什么会有18M之大我也搞不懂,想要程序的戳这密码:mwus