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
留言列表