close

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

https://riptutorial.com/zh-TW/pyqt5/example/29500/%E5%9F%BA%E6%9C%AC%E7%9A%84pyqt%E9%80%B2%E5%BA%A6%E6%A2%9D

 

arrow
arrow
    文章標籤
    PyQt5 Python
    全站熱搜

    KV 發表在 痞客邦 留言(1) 人氣()