close

一、前言

當你五分鐘看完下面兩篇文章開始會寫使用者介面(UI),會發現兩個問題:

【Pyqt5使用者介面開發】Python使用Qt Designer快速拉好使用者介面並讓它活起來

【Pyqt5使用者介面開發】Pyqt5基本觀念及元件lineEdit、pushButton互動信號與槽

1.每次qt designer拉好之後,程式碼要重新複製貼上很麻煩

2.全部的程式碼都寫在一個檔案維護不容易

這時候有沒有辦法不用複製貼上,且每個檔案只負責各自的工作,然後程式依然可以執行呢!?!

答案是有的!! 還不知道物件導向及類(Class)的可以看這篇【Python基礎】什麼是class類:五分鐘看完文章馬上懂物件導向及寫code

 

 

二、我們的目的有2個:

1. ui的介面更動但程式碼不用重打

2. 讓程式碼變得容易維護

 

原本又臭又長的程式碼:

# window.py

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QFrame
import sys

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(454, 177)
        self.pushButton_print = QtWidgets.QPushButton(Form)
        self.pushButton_print.setGeometry(QtCore.QRect(170, 120, 93, 28))
        self.pushButton_print.setObjectName("pushButton_print")
        self.label_print = QtWidgets.QLabel(Form)
        self.label_print.setGeometry(QtCore.QRect(20, 20, 51, 61))
        self.label_print.setObjectName("label_print")
        self.lineEdit_print = QtWidgets.QLineEdit(Form)
        self.lineEdit_print.setGeometry(QtCore.QRect(80, 20, 351, 61))
        self.lineEdit_print.setObjectName("lineEdit_print")

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.pushButton_print.setText(_translate("Form", "點我開始"))
        self.label_print.setText(_translate("Form", "顯示:"))

class MainFrame(QFrame, Ui_Form):
    def __init__(self, parent=None):
        super(MainFrame, self).__init__(parent) # 調用父類把子類對象轉為父類對象
        # 調用介面
        self.setupUi(self) 
        
        # 信號
        self.pushButton_print.clicked.connect(self.calculation) # 信號與槽連接
        
    # 自訂槽函數
    def calculation(self):
        a = 1
        b = 2
        c = a + b
        d = c * 2
        self.lineEdit_print.setText('恩哥好帥' + str(d)) # .setText方法讓文字顯示在lineEdit上
            

if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainFrame = MainFrame()
    mainFrame.show()
    sys.exit(app.exec_())

其實仔細看會發現不就分成三個部份而已嗎!!?

1.class Ui_Form:負責讓介面出來,qt designer自動產生的

2.class MainFrame:負責自訂的方法及運算

3.if __name__ == '__main__':負責執行程式

如果分成三個檔案寫不就很容易維護而且可以用qt designer一直換介面就好

 

三、2個步驟幫你搞定

把原先window.py的程式碼直接變成兩個py檔:window.py及mainModel.py

把原本檔案中間剖開一半,貼到mainModel.py而已,套件包一樣import進去

特別的是在mainModel.py 加上from window import Ui_Form 把window的類匯入讓這邊可以用

 

# window.py

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QFrame
import sys

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(454, 177)
        self.pushButton_print = QtWidgets.QPushButton(Form)
        self.pushButton_print.setGeometry(QtCore.QRect(170, 120, 93, 28))
        self.pushButton_print.setObjectName("pushButton_print")
        self.label_print = QtWidgets.QLabel(Form)
        self.label_print.setGeometry(QtCore.QRect(20, 20, 51, 61))
        self.label_print.setObjectName("label_print")
        self.lineEdit_print = QtWidgets.QLineEdit(Form)
        self.lineEdit_print.setGeometry(QtCore.QRect(80, 20, 351, 61))
        self.lineEdit_print.setObjectName("lineEdit_print")

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.pushButton_print.setText(_translate("Form", "點我開始"))
        self.label_print.setText(_translate("Form", "顯示:"))

# mainModel.py

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QFrame
import sys
from window import Ui_Form # 把window的類匯入讓這邊可以用



class MainFrame(QFrame, Ui_Form):
    def __init__(self, parent=None):
        super(MainFrame, self).__init__(parent) # 調用父類把子類對象轉為父類對象
        # 調用介面
        self.setupUi(self) 
        
        # 信號
        self.pushButton_print.clicked.connect(self.calculation) # 信號與槽連接
        
    # 自訂槽函數
    def calculation(self):
        a = 1
        b = 2
        c = a + b
        d = c * 2
        self.lineEdit_print.setText('恩哥好帥' + str(d)) # .setText方法讓文字顯示在lineEdit上
            

if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainFrame = MainFrame()
    mainFrame.show()
    sys.exit(app.exec_())

這樣不就把介面跟寫程式的地方分開了,不會換新介面就要重寫程式碼了!

聰明的你一定想到了,這時候再把mainModel.py的if __name__ == '__main__':下面拆出來,不就實現我們的二大目的了嗎!!!

把mainModel.py拆成mainModel.py(負責寫方法)及main.py(負責執行),

跟上面一樣,把mainModel.py切一半把if __name__ == '__main__':後面貼到main.py上,套件包都給他

加上一句from mainModel import MainFrame 把mainModel的類import進來讓我們可以用

 

# mainModel.py

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QFrame
import sys
from window import Ui_Form # 把window的類匯入讓這邊可以用



class MainFrame(QFrame, Ui_Form):
    def __init__(self, parent=None):
        super(MainFrame, self).__init__(parent) # 調用父類把子類對象轉為父類對象
        # 調用介面
        self.setupUi(self) 
        
        # 信號
        self.pushButton_print.clicked.connect(self.calculation) # 信號與槽連接
        
    # 自訂槽函數
    def calculation(self):
        a = 1
        b = 2
        c = a + b
        d = c * 2
        self.lineEdit_print.setText('恩哥好帥' + str(d)) # .setText方法讓文字顯示在lineEdit上

# main.py

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QFrame
import sys
from mainModel import MainFrame # 把mainModel的類import進來讓我們可以用


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainFrame = MainFrame()
    mainFrame.show()
    sys.exit(app.exec_())

這樣就拿到三個檔案了main.py(執行)、mainModel.py(方法及運算)及window.py(視窗),

執行main就可以跑出視窗了!!隨時更新UI也沒問題!!

image

 

四、後記

記得把每個包沒用到的套件刪除阿~~~~~

如果專案很大的話,可以分得更細!把負責運算的、負責讀取資料的等等都是一個py檔案!

再匯入具體化成物件來用就好了!

 

arrow
arrow
    創作者介紹
    創作者 恩哥Python 的頭像
    恩哥Python

    恩哥Python量化教室-零基礎也能學會Python

    恩哥Python 發表在 痞客邦 留言(0) 人氣()