荒废博客多时,主要是平时太懒,写完的代码都存着电脑上,去写博客又浪费时间,但随着代码越来越多,我发现好多曾经学过的东西都忘了(毕竟写代码的时候懒得注释)所以,从现在起养成写博客的好习惯,好了,废话不多说,下面介绍一下第一个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('<<Front') self.bottom = QLabel('Label:') self.lab1 = Button('Label1',None) self.lab2 = Button('Label2',None) self.lab3 = Button('Label3',None) self.lab4 = Button('Label4',None) self.editLabel = QLineEdit('')#行编辑 self.editLabel.setToolTip('此处可给标签按钮换信息') self.editLabel.setDragEnabled(True)#让里面的文字可拖拽 self.text = QTextEdit('')#编辑栏,这里我主要让他显示标签的信息 self.text.setToolTip('显示标签信息')#下面是网格布局添加组件,参数分别是行列,跨过的行列 grid.addWidget(self.sc,1,0,5,7) grid.addWidget(self.text,1,7,5,2) grid.addWidget(self.next,6,2,1,1) grid.addWidget(self.front,6,1,1,1) grid.addWidget(self.lab1,7,1) grid.addWidget(self.lab2, 7, 2) grid.addWidget(self.lab3, 7, 3) grid.addWidget(self.lab4, 7, 4) grid.addWidget(self.bottom,8,1) grid.addWidget(self.editLabel,8,2,1,5) def nextButton(self,file): ''' 点击按钮会发生的动作,主要是下一张图片,和上一张图片 ''' icon = QLabel() icon.setPixmap(QPixmap(file)) self.sc.setWidget(icon) 不得不说,只要开头工作做好了,下面写起来并不是很难,而且函数都可以看到名字就知道像网格布局,滑动窗口,另外说一句,每个部件都可以指定一个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
