首先你要有 3.10 及以上版本的 python
pip install -r requirements.txt
python main.py
-
通过 UI 进行交互控制
-
实现对扩散的即时模拟功能
2.1 按照数学公式实现一个二维扩散系统
2.2 通过颜色回显展示平面的粗略情况
2.3 实时显示回显中特定位置的梯度图像
2.4 通过画笔即时编辑系统
2.5 自定义物质之间的反应关系
-
提供高自由度的配置方案
3.1 实现简单的配置文件修改
3.2 提供更精细的参数调节控件
-
通过适当的方法将模拟的结果导出
4.1 截取扩散过程的某一瞬间导出
4.2 将对应位置的图表导出
-
[主界面类] MainWindow
继承自 MSFluentWindow
方法:构建图形化界面
属性:导航栏、各种子页面
-
[子页面类] HomeInterface TasksInterface SettingInterface
继承自 ScrollArea
方法:界面初始化、添加选项卡
属性:控制按钮选项卡、调参控件
-
[按钮选项卡类] PushSettingCard PushSettingCardStr
继承自 SettingCard
方法:按钮事件处理
属性:按钮、按钮状态
-
[图片横幅类] BannerWidget
继承自 QWidget
方法:横幅绘制
属性:图片
-
[扩散模拟内核类] imageProc
方法:运行单帧、渲染结果、运行循环
属性:模拟场地矩阵、扩散参数配置、颜色回显
-
[配置列表类] Config
方法:加载配置、保存配置、设置配置
属性:配置文件
-
[矩阵类] array
方法:矩阵基本运算、扩散运算
属性:矩阵的值
-
[颜色回显类] showRender
方法:鼠标事件处理
属性:渲染矩阵、图表、画笔
-
[图表类] plotManager
方法:渲染图表、导出图表
属性:坐标轴、散点数据
-
[画笔类] showPaint
方法:在指定矩阵上绘制
属性:控制按钮、画笔参数配置
图表类 plot2D plot3D 继承自 plotObserver
class plot2D(plotObserver):
class plot3D(plotObserver):
它们被实例化时,会插入到 showRender 的 observers 列表中
class showRender:
observers = []
def attachObserver(self, observer: plotObserver):
self.observers.append(observer)
class plot2D(plotObserver):
def __init__(self, rdr: showRender, fig, grid, gidx, rate):
# ...
rdr.attachObserver(self)
当 showRender 产生一次更新时,会触发列表中所有类的 updatePlot() 方法
class showRender:
def renderFrame(self):
# ...
for observer in self.observers:
observer.updatePlot()
图表工厂类 plotManager 提供图表界面的创建、排版与布局 它通过 createPlot() 方法的参数,来决定工厂生产 plot2D 还是 plot3D 同时也提供两种默认的排布,即 2D | 3D 和 3D | 2D,以建造出整个图表界面
class plotManager:
def createPlot(self, type):
if self.gidx >= self.gwidth:
return None
if type == 0:
plot = plot2D(self.rdr, self.fig, self.grid, self.gidx, self.p2drate)
else:
plot = plot3D(self.rdr, self.fig, self.grid, self.gidx, self.p3drate)
self.gidx += 1
self.plots.append(plot)
return plot
def createDefaultPlot(self):
self.createPlot(0)
self.createPlot(1)
def createDefaultPlotReverse(self):
self.createPlot(1)
self.createPlot(0)
配置界面的按钮事件函数,重复度极高,可以利用函数闭包批量生成
先批量生成类型转换函数
def __convertGenerator(self, type):
def __convert(value):
if type == "bool":
return value == "True"
elif type == "int":
return int(value)
elif type == "float":
return float(value)
else:
return value
return __convert
再根据类型批量生成按钮事件函数
def __onCardClickedGenerator(self, card: PushSettingCard, configname: str, type: str = "float"):
# ...
ledit.setText(str(config.get_value(configname)))
def __onCardClicked():
if ledit.text():
config.set_value(configname, self.__convertGenerator(type)(ledit.text()))
ledit.setText(str(config.get_value(configname)))
return __onCardClicked