PyQt 是一個python的套件,應用在視窗應用程式,可以幫助完成一個GUI介面,把這幾天study紀錄一下,並做一個可以下載照片到小應用
現在本機中安裝套件
pip install pyqt5 pip install PyQt5-sip pip install pyqt5-tools
pyqt5-tools是可會給我們一個設計工具,一開始寫code前當然要先有個UI介面的雛型出來囉~ designer.exe來設計UI介面用拖拉點選方式完成,也可以直接用code來硬幹,可是還是用這設計工具比較方便~我的路徑是在如下
設計工具路徑
C:\Users\{PC_Name}\AppData\Local\Programs\Python\Python37-32\Lib\site-packages\pyqt5_tools\Qt\bin\designer.exe
設計UI介面
一開始點開會出現這視窗,通常我都是點選Main Window
把想要的widget拉進來,位置屬性那些都可以在右邊的Property Editor完成,完成後存檔後,它的預設副檔名為.ui,我們要把它轉為.py,到.ui目的資料夾開啟cmd,把下列指令輸入到cmd就可以完成轉換(Note: 沒有大括號喔XD只是提示)
pyuic5 {我的PyQt檔名}.ui > {我的PyQt檔名}.py
加入UI編寫Code
剛剛拉的圖就變成如下的code了,剛說過了,也可以自己打,可是就很麻煩,拉一拉就簡單多了
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, mainWindow):
mainWindow.setObjectName("mainWindow")
mainWindow.resize(550, 200)
mainWindow.setIconSize(QtCore.QSize(10, 10))
self.centralwidget = QtWidgets.QWidget(mainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(0, 50, 81, 51))
font = QtGui.QFont()
font.setPointSize(11)
self.label.setFont(font)
self.label.setObjectName("label")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(90, 60, 311, 31))
self.lineEdit.setObjectName("lineEdit")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(420, 58, 100, 40))
self.pushButton.setObjectName("pushButton")
# kevin加入------ EXIT
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setGeometry(QtCore.QRect(420, 130, 100, 40))
self.pushButton_2.setObjectName("pushButton_2")
# 分別是x, y, 長, 寬
self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
self.progressBar.setGeometry(QtCore.QRect(90, 100, 311, 22))
self.progressBar.setProperty("value", 0)
self.progressBar.setObjectName("progressBar")
self.label_count = QtWidgets.QLabel(self.centralwidget)
self.label_count.setGeometry(QtCore.QRect(170, 130, 121, 55))
font = QtGui.QFont()
font.setPointSize(16)
font.setBold(True)
font.setWeight(75)
font.setStrikeOut(False)
self.label_count.setFont(font)
self.label_count.setObjectName("label_count")
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setGeometry(QtCore.QRect(10, 10, 61, 51))
self.label_3.setText("")
self.label_3.setPixmap(QtGui.QPixmap("test.jpg"))
self.label_3.setScaledContents(True)
self.label_3.setObjectName("label_3")
mainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(mainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 550, 22))
self.menubar.setObjectName("menubar")
mainWindow.setMenuBar(self.menubar)
self.retranslateUi(mainWindow)
QtCore.QMetaObject.connectSlotsByName(mainWindow)
def retranslateUi(self, mainWindow):
_translate = QtCore.QCoreApplication.translate
mainWindow.setWindowTitle(_translate("mainWindow", "Kevin_Downloader"))
self.label.setText(_translate("mainWindow", " Your album URL:"))
self.pushButton.setText(_translate("mainWindow", "Download "))
self.pushButton_2.setText(_translate("mainWindow", "Exit"))
還要加入一個main.py來當主程式,來做一些按鈕的事件處理XD
"""
Created on 2019/09/26
@author: kevin
"""
from PyQt5 import QtWidgets
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import QDialog, QApplication, QMainWindow,QMessageBox
from UI import Ui_MainWindow
import re
import sys
from crawl import Connect
import os
class PyMainWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super(PyMainWindow, self).__init__()
self.setupUi(self)
self.progressBar.setValue(0)
# 綁定按鈕的事件處理
self.pushButton.clicked.connect(self.go_button)
self.pushButton_2.clicked.connect(self.exit)
self.label_count.setText('- 張')
self.show()
def exit(self):
print('exit')
sys.exit(app.exec_())
def go_button(self):
qq= WaringWindow()
urls= self.lineEdit.text()
pat5 = re.compile(.......)
if urls=="":
qq.warning()
elif pat5.search(urls) == None :
qq.warning2()
else:
print('else')
self.pushButton.setText("Downloading...")
self.threads= []
downloader= WorkerThread(urls)
downloader.data_downloaded.connect(self.send_signal)
self.threads.append(downloader)
downloader.start()
def send_signal(self,data):
# 邏輯處理要寫在這邊,不能寫在Thread的run()會出事
if data.status == 0:
qq = WaringWindow()
qq.warning3()
print('in')
self.label_count.setText('總共: {}張'.format(data.total_pic))
progress_percent = round((data.count / data.total_pic) * 100, 1)
self.progressBar.setValue(progress_percent)
if progress_percent == 100:
done = DoneWindow()
if done.msg() == 'ok':
print('OK')
self.reset()
self.pushButton.setText("download")
else:
print('CANCLE')
self.pushButton.setText("download")
def reset(self):
print ('RESET')
self.progressBar.setValue(0)
self.label_count.setText('- 張')
self.lineEdit.clear()
class WaringWindow(QtWidgets.QWidget):
def __init__(self):
super(WaringWindow, self).__init__()
def warning(self):
QMessageBox.warning(self,'warning',"ERROR_ blank URL.",QMessageBox.Ok )
def warning2(self):
QMessageBox.warning(self,'warning',"Wrong URL, make sure again.",QMessageBox.Ok)
def warning3(self):
QMessageBox.warning(self,'warning',"There are exist same filename in the path",QMessageBox.Ok)
class DoneWindow(QtWidgets.QWidget):
def __init__(self):
super(DoneWindow, self).__init__()
def msg(self):
msgbox= QMessageBox.information(self,'提示',"下載完成",QMessageBox.Ok | QMessageBox.Cancel)
if msgbox==QMessageBox.Ok:
answer = 'ok'
else:
answer = 'cancle'
return answer
class WorkerThread(QThread):
data_downloaded = pyqtSignal(object)
def __init__(self,url): # pyqtSignal(object) 的object 會傳給初始化的url
QThread.__init__(self)
self.url=url
self.count = 0
self.total_pic = 0
# Thread的run()
def run(self):
Con = Connect(self.url)
imgs = Con.get_url()
self.total_pic = len(imgs)
title = Con.get_title()
for count, img in enumerate(imgs):
filename = 'D://pic/{}_{}.jpg'.format(title, count)
if os.path.exists(filename):
self.status = 0
self.data_downloaded.emit(self)
break;
else:
with open(filename, 'wb') as f:
f.write(img.content)
f.flush()
self.count += 1
#丟資料到def send_signal(self,data)
self.data_downloaded.emit(self)
#最重要一定要加入的
if __name__ == '__main__':
app = QApplication(sys.argv)
MainWindow = QMainWindow()
ui = PyMainWindow()
ui.show()
sys.exit(app.exec_())
上面是一個貼上網址並自動下載圖片的小應用,下載的圖片就是男生的最愛XD,有自己寫一些爬蟲程式寫在另一個class就不記錄了
流程:
上面我寫的程式碼Function流程,PyQt5有很多不錯method可以用,
可以多參考官方文件: https://www.riverbankcomputing.com/static/Docs/PyQt5/
最後呈現結果
要把PyQt打包成.exe的話要裝pyinstaller模組
pip install pyinstaller
轉為CMD的指令為如下:
pyinstaller -F {我的PyQt檔名}.py
其中-F這個引數代表將所有內容打包成一個exe檔案。如果不帶這個引數的話,會變成是一大堆檔案,
當一長串資訊閃過,最後停止後,就大功造成了,可以發現Source路徑下多出了一個dist資料夾,裡面就是轉出的結果 exe 檔案!
Reference:
https://www.riverbankcomputing.com/static/Docs/PyQt5/
https://dotblogs.com.tw/zeus83157/2018/06/23/011440
https://www.youtube.com/watch?v=FaZL6_s8z0s

copy paste?
Not at all. To tell the truth, I'm coding round the clock.