利用MVC設計模式構建GUI(PyQt5版)
今天介紹一個PyQt5中利用MVC設計模式構建GUI的例子,這個案例來源於《MATLAB面向物件程式設計——從入門到設計模式(第2版)》第7章內容,關於存取款的GUI工具設計,詳情請參考127~160頁面。
利用PyQt5最終建立的介面如下:
接下來聊一聊,具體的實現細節。
與Matlab設計的版本對比,唯一的區別在於事件處理機制的實現方式不同而已。
PyQt5/Qt 中稱為訊號和槽,用於物件之間的通訊,當指定事件發生,一個事件訊號會被髮射,槽可以被任何Python指令碼呼叫。當和槽連線的訊號被髮射時,槽會被呼叫。自定義事件由PyQt5.QtCore
中的pyqtSignal
方法完成。
Matlab 中的handle
類也已經幫我們實現好了事件處理機制,除了控制元件自帶的,諸如 Callback
、ButtonPushedFcn
等屬性(也可以理解成內建事件)外,也可以自定義事件(events
定義),然後通過notify
方法進行事件的註冊(對應於Qt中的訊號發射!),最後由addlistener
監聽事件(相當於槽的作用)。
實現的模型類原始碼如下:
python
# !/usr/bin/env python3
# -*- coding:utf-8 -*-
from PyQt5.QtCore import QObject, pyqtSignal
class BalanceModel(QObject):
balance_changed = pyqtSignal()
def __init__(self, balance):
super(BalanceModel, self).__init__()
self.balance = balance
def withdraw(self, val):
self.balance -= val
self.balance_changed.emit()
def deposit(self, val):
self.balance += val
self.balance_changed.emit()
由語句balance_changed = pyqtSignal()
自定義了一個事件訊號:balance_changed
。在模型類中,當取款或存款發生時,餘額發生了改變,即balance_changed
事件訊號觸發了,會發布(發射)訊息(通過繫結emit()方法)。接下來需要在檢視類中定義所謂的槽函式,即監聽balance_changed
事件訊號,做出響應。
檢視類的原始碼如下:
python
# !/usr/bin/env python3
# -*- coding:utf-8 -*-
from PyQt5.QtWidgets import (QWidget,
QGridLayout,
QLabel,
QLineEdit,
QPushButton)
from PyQt5.QtCore import Qt
from BalanceController import BalanceController
class BalanceView(QWidget):
def __init__(self, m_obj):
super(BalanceView, self).__init__()
self.m_obj = m_obj
self.c_obj = self.make_controller() # Controller object
self.balance_label = None
self.balance_text = None
self.rmb_label = None
self.rmb_text = None
self.withdraw_btn = None
self.deposit_btn = None
self.build_app()
self.attach2controller(self.c_obj)
self.m_obj.balance_changed.connect(self.update_balance)
def build_app(self):
self.setVisible(False)
self.resize(300, 120)
self.setWindowTitle('存取款介面')
self.balance_label = QLabel('Balance')
self.balance_label.setAlignment(Qt.AlignRight)
self.balance_text = QLineEdit()
self.balance_text.setAlignment(Qt.AlignRight)
self.balance_text.setReadOnly(True)
self.balance_text.setText('0')
self.rmb_label = QLabel('RMB')
self.rmb_label.setAlignment(Qt.AlignRight)
self.rmb_text = QLineEdit()
self.rmb_text.setAlignment(Qt.AlignRight)
self.rmb_text.setText('0')
self.withdraw_btn = QPushButton('withdraw')
self.withdraw_btn.setAutoFillBackground(True)
self.deposit_btn = QPushButton('deposit')
main_layout = QGridLayout(self)
main_layout.setHorizontalSpacing(15)
main_layout.setVerticalSpacing(15)
main_layout.addWidget(self.balance_label, 0, 0, 1, 2)
main_layout.addWidget(self.balance_text, 0, 2, 1, 2)
main_layout.addWidget(self.rmb_label, 1, 0, 1, 2)
main_layout.addWidget(self.rmb_text, 1, 2, 1, 2)
main_layout.addWidget(self.withdraw_btn, 2, 0, 1, 2)
main_layout.addWidget(self.deposit_btn, 2, 2, 1, 2)
self.setLayout(main_layout)
self.setVisible(True)
self.update_balance()
def update_balance(self):
self.balance_text.setText(str(self.m_obj.balance))
def make_controller(self):
controller = BalanceController(self, self.m_obj)
return controller
def attach2controller(self, controller):
self.withdraw_btn.clicked.connect(controller.withdraw_btn_callback)
self.deposit_btn.clicked.connect(controller.deposit_btn_callback)
對於按鈕控制元件,需要connect
方法監聽該事件訊號: self.m_obj.balance_changed.connect(self.update_balance)
控制器類原始碼如下:
python
# !/usr/bin/env python3
# -*- coding:utf-8 -*-
class BalanceController:
def __init__(self, v_obj, m_obj):
self.v_obj = v_obj
self.m_obj = m_obj
def withdraw_btn_callback(self):
val = float(self.v_obj.rmb_text.displayText())
self.m_obj.withdraw(val)
def deposit_btn_callback(self):
val = float(self.v_obj.rmb_text.displayText())
self.m_obj.deposit(val)
最後,我們可以自定義指令碼 balanceApp.py
將MVC的原始碼組合起來,就可以執行出這個GUI小工具了,具體如下動圖所示:
至此,我們介紹了一個比較完整的利用MVC設計模式構建GUI的方法!希望您喜歡,並且可以從中獲得有用的東西。
本文完整程式碼,請在gzh內回“pyqt5_mvc”進行下載。
【往期推薦】
- 手把手教你,一個案例學會用Matlab App Designer設計文字識別工具(附原始碼)
- 矩陣2-範數化的向量化方法 (qq.com)
- texStudio主題配置 (qq.com)
- 送福利啦 (qq.com)
- 如何用Matlab一鍵下載B站高清影片(下) (qq.com)
- Python中的裝飾器 (qq.com)
- MATLAB 風格指南 2.0 (qq.com)
- 匿名函式(Anonymous Function) (qq.com)
- 猜猜今天的乾貨有哪些? (qq.com)
- 分享爬取Matlab中文論壇基礎討論的原始碼 (qq.com)
- 如何用Matlab一鍵下載B站高清影片(上) (qq.com)
- 爬取某學者主頁上的文獻 (qq.com)