MVC结构是之model-view-controller三层架构的开发框架,用以将项目界面和逻辑进行解耦分析,便于维护。与WPF的MVVM相似。
项目开发做了一个秒表试手:
1.项目架构如下
- controller:用于放置界面的控制逻辑
- model:用于放置 各个实际的单元模块
- view:用于放置界面文件
- res:用于方式图标等资源文件
- main:程序主入口
2.view
设计一个秒表的界面,就一个显示显示时间,一个启动停止按钮。
# _*_ coding:utf-8 _*_
from PyQt6.QtWidgets import QWidget,QLCDNumber,QPushButton,QVBoxLayout
from PyQt6.QtGui import QIcon
from PyQt6.QtCore import Qt
class StopWatchView(QWidget):
"""
秒表构造函数
"""
def __init__(self):
"""
构造函数
"""
super().__init__()
self.setWindowTitle("Stop Watch")
self.setWindowIcon(QIcon(r"res/time04.ico"))
self.initUI()
def initUI(self):
"""
初始化界面
"""
# Set window location and size.
self.setGeometry(400,300,300,200)
# 显示时间
self.lcd = QLCDNumber()
self.lcd.setDigitCount(6)
self.lcd.display('0.00')
# Show button.
self.btn = QPushButton('Start')
self.btn.setStyleSheet('background-color:darkgray')
# Set layout.
vboxlayout = QVBoxLayout()
self.setLayout(vboxlayout)
vboxlayout.addWidget(self.lcd)
vboxlayout.addSpacing(5)
vboxlayout.addWidget(self.btn)
3.model
编写一个即使单元模块,固定时间刷新一次时间。
# _*_ coding:utf-8 _*_
import sys
import time
from PyQt6.QtCore import QObject,pyqtSignal
class ClockServer(QObject):
"""Clock server"""
update_time = pyqtSignal(str) # 时间更新信号
__isrun = False # Running flag.
@property
def isrun(self):
"""get run flag."""
return self.__isrun
@isrun.setter
def isrun(self,value):
"""set run flag."""
if type(value) is bool:
self.__isrun = value
def run(self):
"""start server"""
while True:
start_time = time.time()
while self.isrun:
self.update_time.emit("{0:.2f}".format(time.time()-start_time))
time.sleep(0.01)
4.controller
view和model的中间模块,用来整个界面和模块,控制具体的显示逻辑
# _*_ coding:utf-8 _*_
import sys
from model.clockutil import ClockServer
from view.stopwatchview import StopWatchView
from PyQt6.QtCore import Qt,QThread
class StopWatchController:
"""View controller"""
def __init__(self):
self.view = StopWatchView()
self.view.btn.clicked.connect(self.btn_onclick)
self.view.show()
self.timeserver = ClockServer()
self.timeserver.update_time.connect(self.view.lcd.display)
self.thread = QThread()
self.timeserver.moveToThread(self.thread)
self.thread.started.connect(self.timeserver.run)
self.thread.start()
def btn_onclick(self):
"""按键响应事件"""
if self.view.btn.text() == "Start":
self.timeserver.isrun = True
self.view.btn.setText("Stop")
else:
self.timeserver.isrun = False
self.view.btn.setText("Start")
5.main
写了一个main文件作为软件的启动入口。
# _*_ coding:utf-8 _*_
import sys
from controller.stopwatchcontroller import StopWatchController
from PyQt6.QtWidgets import QApplication
if __name__ == "__main__":
"""main"""
app = QApplication(sys.argv)
stopwatch = StopWatchController()
sys.exit(app.exec())
6.结果
总结:
该示例将界面和逻辑分离,界面只是界面,不过实现的不是很好,比较好的逻辑会将界面和逻辑完全隔离开,避免控制逻辑直接方位界面的控件,带进一步学习完善。