概述
目前有关于PyQt5的系统的教程较少,毕竟Python的主要用途也不是做图形界面。但是鉴于作者最近想将很多的感兴趣的研究成果打包到一个应用里展示,而这些成果移植到Python会具有很强的可读性,所以就产生了用PyQt5来做GUI的念头。不过作者虽然听说Python的大名很多年,但是认真的用Python做一个稍复杂规模的应用还是第一回,制作过程中很多地方都是参考用其他语言做GUI Projct的经验和Qt(C++)的官方文档,或者干脆自己摸索出来的。
本应用是作者秉持“可扩展+最大程度降低重复代码”的理念制作完成的。
设计目标
为了便于后续对代码的修改管理,在设计最初就应该定好一个合理的框架。为了做到这点,作者个人认为有以下几点是必须要遵守的。
1) 禁止组件的个性化命名。这点是很重要的,虽然将某个按钮按照它调用的函数来做相关的命名后,在Debug的时候是很容易修正一些逻辑设计上的问题的。但是当应用越做越大的时候,个性化的命名会“锁住”你的设计框架,从而在人们想要修改设计思路的时候,感到如陷泥沼般的困难。
2) 设计一个函数来批量的”new”你的组件,将你的组件和数据统一放到一个“容器”里,对组件和数据来说这个容器是字典较为合适,而字典的最底层往往是一个列表较为合适。
3) 用属性来代替global变量,毕竟global变量总给人一种很不工整的感觉。
4) 设计每一个页面的时候只写布局和指定每个控件信号对应的槽。
5) 尽量避免定时器的使用。
6) 将鼠标和键盘绑定在和菜单相关的对象上,而非窗体对象本身。
设计框架
1) 设计一个父类,其中包含存储控件和全局变量的容器。
2) 设计一个函数统一管理action。
3) 设计一个函数统一管理menu Bar。
4) 设计一个函数,使得该函数针对同类型和槽函数均相同的组件可以批量创建。
5) 设计一个函数,使得该函数可以自动读取存储的数据,并且根据读取的内容调整相关的控件的各种参数。
5) 针对每一个页面,设计一个函数来进行布局和指定每个控件信号对应的槽。
6) 针对每一个页面,设计一个函数来写自定义槽。
6) 设计一个代数模块来统一管理自定义的代数计算相关的类。
7) 设计一个画布模块来统一管理后台的即时动画计算和静态图形的绘制。
代码(框架分部)
容器:
1 #!/usr/bin/python 2 3 4 class MainData: 5 """ 6 frame of page data about PyQt5 7 """ 8 9 def __init__(self): 10 self.action = dict() 11 self.canvas = dict() 12 self.control = {"QLabel": [], "QTabWidget": [], "QPushButton": [], "QTextEdit": [], 13 "QRadioButton": [], "QComboBox": [], "QSpinBox": [], "QTableWidget": [], "QLCDNumber": []} 14 self.controlData = dict() 15 16 def controlClear(self): 17 """ 18 remove all the controls except menuBar before open a new page 19 """ 20 self.control = {"QLabel": [], "QTabWidget": [], "QPushButton": [], "QTextEdit": [], 21 "QRadioButton": [], "QComboBox": [], "QSpinBox": [], "QTableWidget": [], "QLCDNumber": []} 22 23 def addFrame(self, imageName): 24 """ 25 add a empty dictionary to record page data 26 """ 27 self.controlData[imageName] = dict() 28 self.controlData[imageName]["QRadioButton"] = {"isChecked": []} 29 self.controlData[imageName]["QComboBox"] = {"itemText": [], "currentIndex": []} 30 self.controlData[imageName]["QSpinBox"] = {"value": []} 31 self.controlData[imageName]["QTableWidget"] = {"data": []} 32 self.controlData[imageName]["QLCDNumber"] = {"value": []} 33 self.controlData[imageName]["save"] = [] 34 35 def controlDataClear(self, imageName): 36 """ 37 remove data before refresh current page 38 """ 39 self.controlData[imageName]["QRadioButton"]["isChecked"] = [] 40 self.controlData[imageName]["QComboBox"]["itemText"] = [] 41 self.controlData[imageName]["QComboBox"]["currentIndex"] = [] 42 self.controlData[imageName]["QSpinBox"]["value"] = [] 43 self.controlData[imageName]["QTableWidget"]["data"] = [] 44 self.controlData[imageName]["QLCDNumber"]["value"] = [] 45 self.controlData[imageName]["save"] = []
窗体:
1 #!/usr/bin/python 2 # coding=utf-8 3 4 from __future__ import division 5 from MainData import MainData 6 from CanvasManager import * 7 from AlgorithmManager import * 8 from PyQt5.QtCore import Qt 9 from PyQt5.QtGui import (QIcon, QFont) 10 from PyQt5.QtWidgets import (qApp, 11 QAction, 12 QComboBox, 13 QDesktopWidget, 14 QFileDialog, 15 QGridLayout, 16 QInputDialog, 17 QRadioButton, 18 QLabel, 19 QLCDNumber, 20 QMainWindow, 21 QMessageBox, 22 QPushButton, 23 QSpinBox, 24 QTableWidget, 25 QTableWidgetItem, 26 QTabWidget, 27 QTextEdit, 28 QToolTip, 29 QWidget) 30 31 32 # noinspection PyNonAsciiChar 33 class App(QMainWindow, MainData): 34 """ 35 @ 36 """ 37 38 # noinspection PyArgumentList,PyMissingConstructor 39 def __init__(self): 40 # noinspection PyCompatibility 41 QMainWindow.__init__(self) 42 43 # noinspection PyCallByClass,PyTypeChecker 44 QToolTip.setFont(QFont('SansSerif', 10)) 45 self.setGeometry(100, 100, 900, 550) 46 qr = self.frameGeometry() 47 cp = QDesktopWidget().availableGeometry().center() 48 qr.moveCenter(cp) 49 self.move(qr.topLeft()) 50 self.setWindowTitle('MathDemo') 51 self.setWindowIcon(QIcon('python.png')) 52 self.setWindowFlags(Qt.WindowStaysOnTopHint) 53 54 self.actionLoad() 55 56 self.menuBarLoad() 57 58 ############################################# 59 # set current image that you are operating. # 60 ############################################# 61 self.currentImage = "" 62 self.rainImage() 63 64 self.statusBar().showMessage('Ready') 65 66 self.show() 67 68 def actionLoad(self): 69 """ 70 set MainData.action 71 """ 72 73 self.action["showOpenDialog"] = QAction('Open File', self) 74 self.action["showOpenDialog"].setIcon(QIcon('open.png')) 75 self.action["showOpenDialog"].setShortcut('Ctrl+O') 76 self.action["showOpenDialog"].setStatusTip('Open File') 77 self.action["showOpenDialog"].triggered.connect(self.showOpenDialog) 78 79 self.action["qApp.quit"] = QAction('Exit application', self) 80 self.action["qApp.quit"].setIcon(QIcon('exit.jpg')) 81 self.action["qApp.quit"].setShortcut('Ctrl+Q') 82 self.action["qApp.quit"].setStatusTip('Exit application') 83 self.action["qApp.quit"].triggered.connect(qApp.quit) 84 85 self.action["orthogonalTableImage"] = QAction('Orthogonal Table', self) 86 self.action["orthogonalTableImage"].setIcon(QIcon('numpy_logo.jpg')) 87 self.action["orthogonalTableImage"].setShortcut('Ctrl+T') 88 self.action["orthogonalTableImage"].setStatusTip('Orthogonal Table') 89 self.action["orthogonalTableImage"].triggered.connect(self.orthogonalTableImage) 90 91 self.action["convexHullImage"] = QAction('Convex Hull', self) 92 self.action["convexHullImage"].setIcon(QIcon('numpy_logo.jpg')) 93 self.action["convexHullImage"].setShortcut('Ctrl+C') 94 self.action["convexHullImage"].setStatusTip('Convex Hull') 95 self.action["convexHullImage"].triggered.connect(self.convexHullImage) 96 97 self.action["gravitationalSystemImage"] = QAction('Gravitational System', self) 98 self.action["gravitationalSystemImage"].setIcon(QIcon('scipy_logo.jpg')) 99 self.action["gravitationalSystemImage"].setShortcut('Ctrl+G') 100 self.action["gravitationalSystemImage"].setStatusTip('Gravitational System') 101 self.action["gravitationalSystemImage"].triggered.connect(self.gravitationalSystemImage) 102 103 self.action["analyticFunctionImage"] = QAction('Analytic Function', self) 104 self.action["analyticFunctionImage"].setIcon(QIcon('numpy_logo.jpg')) 105 self.action["analyticFunctionImage"].setShortcut('Ctrl+A') 106 self.action["analyticFunctionImage"].setStatusTip('Analytic Function') 107 self.action["analyticFunctionImage"].triggered.connect(self.analyticFunctionImage) 108 109 self.action["sourceCodeImage"] = QAction('Source Code', self) 110 self.action["sourceCodeImage"].setShortcut('F2') 111 self.action["sourceCodeImage"].setStatusTip('Source Code') 112 self.action["sourceCodeImage"].triggered.connect(self.sourceCodeImage) 113 114 def menuBarLoad(self): 115 """ 116 set MainWindow.menuBar 117 """ 118 self.statusBar() 119 menubar = self.menuBar() 120 121 fileMenu = menubar.addMenu('&File') 122 fileMenu.addAction(self.action["showOpenDialog"]) 123 fileMenu.addAction(self.action["qApp.quit"]) 124 125 statisticsMenu = menubar.addMenu('&Statistics') 126 statisticsMenu.addAction(self.action["orthogonalTableImage"]) 127 128 statisticsMenu = menubar.addMenu('&Geometry') 129 statisticsMenu.addAction(self.action["convexHullImage"]) 130 131 statisticsMenu = menubar.addMenu('&Ode') 132 statisticsMenu.addAction(self.action["gravitationalSystemImage"]) 133 134 statisticsMenu = menubar.addMenu('&Complex') 135 statisticsMenu.addAction(self.action["analyticFunctionImage"]) 136 137 statisticsMenu = menubar.addMenu('&Help') 138 statisticsMenu.addAction(self.action["sourceCodeImage"]) 139 140 def controlLayout(self, layout=None, name=None, var=None, position=None, signal=None): 141 """ 142 control layout 143 :param layout: GridLayout = QGridLayout() 144 :param name: name of control, name is a string 145 :param var: var is a dict 146 :param position: position is a list with 4 numeric 147 :param signal: signal function 148 """ 149 if name == "QLabel": 150 # var = {"text": [string]} 151 for j in range(0, len(position)): 152 self.control[name].append(QLabel(var["text"][j])) 153 self.control[name][-1].setAlignment(Qt.AlignCenter) 154 # noinspection PyArgumentList 155 layout.addWidget(self.control[name][-1], position[j][0], position[j][1], position[j][2], position[j][3]) 156 157 if name == "QTabWidget": 158 # var = {"text": [[string]], "widget": [[PyQt5.QtWidgets.QWidget]]} 159 for j in range(0, len(position)): 160 self.control[name].append(QTabWidget()) 161 for k in range(0, len(var["text"][j])): 162 self.control[name][-1].addTab(var["widget"][j][k], self.tr(var["text"][j][k])) 163 # noinspection PyArgumentList 164 layout.addWidget(self.control[name][-1], position[j][0], position[j][1], position[j][2], position[j][3]) 165 166 if name == "QPushButton": 167 # var = {"text": [string]} 168 for j in range(0, len(position)): 169 self.control[name].append(QPushButton(var["text"][j])) 170 # noinspection PyArgumentList 171 layout.addWidget(self.control[name][-1], position[j][0], position[j][1], position[j][2], position[j][3]) 172 if signal is not None: 173 self.control[name][-1].clicked.connect(signal) 174 175 if name == "QTextEdit": 176 # var = {"text": [[string]]} 177 for j in range(0, len(position)): 178 self.control[name].append(QTextEdit()) 179 if len(var["text"]) != 0: 180 if len(var["text"][j]) != 0: 181 for line in var["text"][j]: 182 self.control[name][-1].append(line) 183 # noinspection PyArgumentList 184 layout.addWidget(self.control[name][-1], position[j][0], position[j][1], position[j][2], position[j][3]) 185 186 if name == "QRadioButton": 187 # var = {"text": [string], "isChecked": [bool]} 188 for j in range(0, len(position)): 189 self.control[name].append(QRadioButton(var["text"][j])) 190 self.control[name][-1].setChecked(var["isChecked"][j]) 191 # noinspection PyArgumentList 192 layout.addWidget(self.control[name][-1], position[j][0], position[j][1], position[j][2], position[j][3]) 193 if signal is not None: 194 self.control[name][-1].clicked.connect(signal) 195 196 if name == "QComboBox": 197 # var = {"itemText": [[string]], "currentIndex": [int]} 198 for j in range(0, len(position)): 199 self.control[name].append(QComboBox()) 200 self.control[name][-1].addItems(var["itemText"][j]) 201 if len(var["currentIndex"]) != 0: 202 self.control[name][-1].setCurrentIndex(var["currentIndex"][j]) 203 # noinspection PyArgumentList 204 layout.addWidget(self.control[name][-1], position[j][0], position[j][1], position[j][2], position[j][3]) 205 if signal is not None: 206 self.control[name][-1].currentIndexChanged.connect(signal) 207 208 if name == "QSpinBox": 209 # var = {"range": [[int, int]], "singleStep": [int], "prefix": [string], "suffix": [string], "value": [int]} 210 for j in range(0, len(position)): 211 self.control[name].append(QSpinBox()) 212 self.control[name][-1].setRange(var["range"][j][0], var["range"][j][1]) 213 self.control[name][-1].setSingleStep(var["singleStep"][j]) 214 if len(var["prefix"]) != 0: 215 if len(var["prefix"][j]) != 0: 216 self.control[name][-1].setPrefix(var["prefix"][j]) 217 if len(var["suffix"]) != 0: 218 if len(var["suffix"][j]) != 0: 219 self.control[name][-1].setSuffix(var["suffix"][j]) 220 self.control[name][-1].setValue(var["value"][j]) 221 # noinspection PyArgumentList 222 layout.addWidget(self.control[name][-1], position[j][0], position[j][1], position[j][2], position[j][3]) 223 if signal is not None: 224 self.control[name][-1].valueChanged.connect(signal) 225 226 if name == "QTableWidget": 227 # var = {"headerLabels": [[string]], "data": [numpy.array]} 228 for i in range(0, len(position)): 229 self.control[name].append(QTableWidget(1, 1)) 230 if len(var["headerLabels"]) != 0: 231 if len(var["headerLabels"][i]) != 0: 232 self.control[name][-1].setColumnCount(len(var["headerLabels"][i])) 233 self.control[name][-1].setHorizontalHeaderLabels(var["headerLabels"][i]) 234 if len(var["data"]) != 0: 235 if len(var["data"][i]) != 0: 236 row, column = var["data"][i].shape 237 self.control[name][-1].setRowCount(row) 238 self.control[name][-1].setColumnCount(column) 239 for j in range(0, row): 240 for k in range(0, column): 241 newItem = QTableWidgetItem(str(var["data"][i][j][k])) 242 self.control[name][-1].setItem(j, k, newItem) 243 self.control[name][-1].resizeColumnsToContents() 244 # noinspection PyArgumentList 245 layout.addWidget(self.control[name][-1], position[i][0], position[i][1], position[i][2], position[i][3]) 246 247 if name == "QLCDNumber": 248 # var = {"value": [int]} 249 for j in range(0, len(position)): 250 self.control[name].append(QLCDNumber(self)) 251 if len(var["value"]) != 0: 252 if len(var["value"][j]) != 0: 253 self.control[name][-1].display(var["value"][j]) 254 else: 255 self.control[name][-1].display(0) 256 # noinspection PyArgumentList 257 layout.addWidget(self.control[name][-1], position[j][0], position[j][1], position[j][2], position[j][3]) 258 259 def imageRead(self, imageName=None): 260 """ 261 load data into current page, or write data from current page. 262 """ 263 if len(self.control["QRadioButton"]) != 0: 264 length = len(self.control["QRadioButton"]) 265 for j in range(0, length): 266 isChecked = self.controlData[imageName]["QRadioButton"]["isChecked"][j] 267 self.control["QRadioButton"][j].setChecked(isChecked) 268 269 if len(self.control["QComboBox"]) != 0: 270 pass 271 272 if len(self.control["QComboBox"]) != 0: 273 length = len(self.control["QComboBox"]) 274 for j in range(0, length): 275 currentIndex = self.controlData[imageName]["QComboBox"]["currentIndex"][j] 276 self.control["QComboBox"][j].setCurrentIndex(currentIndex) 277 278 if len(self.control["QSpinBox"]) != 0: 279 length = len(self.control["QSpinBox"]) 280 for j in range(0, length): 281 value = self.controlData[imageName]["QSpinBox"]["value"][j] 282 self.control["QSpinBox"][j].setValue(value) 283 284 if len(self.control["QTableWidget"]) != 0: 285 length = len(self.control["QTableWidget"]) 286 for i in range(0, length): 287 data = self.controlData[imageName]["QTableWidget"]["data"][i] 288 row, column = data.shape 289 self.control["QTableWidget"][i].setRowCount(row) 290 self.control["QTableWidget"][i].setColumnCount(column) 291 for j in range(0, row): 292 for k in range(0, column): 293 newItem = QTableWidgetItem(str(data[j][k])) 294 self.control["QTableWidget"][i].setItem(j, k, newItem) 295 self.control["QTableWidget"][i].resizeColumnsToContents() 296 297 if len(self.control["QLCDNumber"]) != 0: 298 length = len(self.control["QLCDNumber"]) 299 for j in range(0, length): 300 value = self.controlData[imageName]["QLCDNumber"]["value"][j] 301 self.control["QLCDNumber"][j].display(value) 302 303 def rainImage(self): 304 """ 305 @ 306 """ 307 self.currentImage = "rainImage" 308 self.controlClear() 309 310 layout = QGridLayout() 311 layout.setSpacing(10) 312 313 # noinspection PyArgumentList 314 widget = QWidget() 315 self.canvas["rainImage"] = RainCanvas(parent=widget) 316 layout.addWidget(self.canvas["rainImage"]) 317 318 widget.setLayout(layout) 319 self.setCentralWidget(widget) 320 321 def orthogonalTableImage(self): 322 """ 323 layout and initialization data 324 """ 325 ########################## 326 # layout of current page # 327 ########################## 328 self.currentImage = "orthogonalTableImage" 329 self.controlClear() 330 331 layout = QGridLayout() 332 layout.setSpacing(10) 333 334 text = ['水平数', '重复次数', '实验次数', '因素数'] 335 position = [[0, 0, 1, 1], [0, 2, 1, 1], [0, 4, 1, 1], [0, 6, 1, 1]] 336 self.controlLayout(layout=layout, name="QLabel", var={"text": text}, position=position, signal=None) 337 338 itemText = [list(map(str, range(2, 10))), list(map(str, range(0, 10)))] 339 position = [[0, 1, 1, 1], [0, 3, 1, 1]] 340 self.controlLayout(layout=layout, name="QComboBox", var={"itemText": itemText, "currentIndex": []}, 341 position=position, signal=self.orthogonalTableImageSignal) 342 343 position = [[0, 5, 1, 1], [0, 7, 1, 1]] 344 self.controlLayout(layout=layout, name="QLCDNumber", var={"value": []}, position=position, signal=None) 345 346 # noinspection PyArgumentList 347 widget = [[QWidget(), QWidget()]] 348 for j in range(0, 2): 349 widgetLayout = QGridLayout() 350 position = [[0, 0, 1, 1]] 351 self.controlLayout(layout=widgetLayout, name="QTableWidget", var={"headerLabels": [], "data": []}, 352 position=position, signal=None) 353 widget[0][j].setLayout(widgetLayout) 354 text = [["Table", "Title"]] 355 position = [[1, 0, 1, 8]] 356 self.controlLayout(layout=layout, name="QTabWidget", var={"text": text, "widget": widget}, 357 position=position, signal=None) 358 359 # noinspection PyArgumentList 360 widget = QWidget() 361 widget.setLayout(layout) 362 self.setCentralWidget(widget) 363 364 ########################################################################### 365 # initialization self.controlData["orthogonalTableImage"] then refresh it # 366 # refresh self.control["orthogonalTableImage"] # 367 ########################################################################### 368 if "orthogonalTableImage" not in self.controlData: 369 self.addFrame("orthogonalTableImage") 370 self.orthogonalTableImageSignal() 371 else: 372 for j in range(0, len(self.control["QComboBox"])): 373 self.control["QComboBox"][j].currentIndexChanged.disconnect(self.orthogonalTableImageSignal) 374 self.imageRead(imageName="orthogonalTableImage") 375 for j in range(0, len(self.control["QComboBox"])): 376 self.control["QComboBox"][j].currentIndexChanged.connect(self.orthogonalTableImageSignal) 377 378 self.statusBar().showMessage('Ready') 379 380 def orthogonalTableImageSignal(self): 381 """ 382 respond of current page(orthogonalTableImage), then write data into MainData.controlData 383 """ 384 self.statusBar().showMessage('Starting generate table and title...') 385 386 ########################################################### 387 # initialization self.controlData["orthogonalTableImage"] # 388 ########################################################### 389 imageName = "orthogonalTableImage" 390 self.controlDataClear(imageName) 391 392 #################################################### 393 # refresh self.controlData["orthogonalTableImage"] # 394 #################################################### 395 for j in range(0, len(self.control["QComboBox"])): 396 itemText = list() 397 for k in range(0, self.control["QComboBox"][j].count()): 398 itemText.append(self.control["QComboBox"][j].itemText(k)) 399 self.controlData[imageName]["QComboBox"]["itemText"].append(itemText) 400 401 currentIndex = self.control["QComboBox"][j].currentIndex() 402 self.controlData[imageName]["QComboBox"]["currentIndex"].append(currentIndex) 403 404 level = int(self.control["QComboBox"][0].currentText()) 405 time = int(self.control["QComboBox"][1].currentText()) 406 obj = OrthogonalTableMap(level, time) 407 row, column = obj.table.shape 408 409 self.controlData[imageName]["QLCDNumber"]["value"].append(row) 410 self.controlData[imageName]["QLCDNumber"]["value"].append(column) 411 412 self.controlData[imageName]["QTableWidget"]["data"].append(obj.table) 413 self.controlData[imageName]["QTableWidget"]["data"].append(obj.title) 414 415 self.controlData[imageName]["save"] = [level, time, obj.table, obj.title] 416 417 ################################################ 418 # refresh self.control["orthogonalTableImage"] # 419 ################################################ 420 for j in range(0, len(self.control["QComboBox"])): 421 self.control["QComboBox"][j].currentIndexChanged.disconnect(self.orthogonalTableImageSignal) 422 self.imageRead(imageName=imageName) 423 for j in range(0, len(self.control["QComboBox"])): 424 self.control["QComboBox"][j].currentIndexChanged.connect(self.orthogonalTableImageSignal) 425 426 if obj.error == 1: 427 self.statusBar().showMessage('Unable to generate title.') 428 else: 429 self.statusBar().showMessage('Table and title generated.') 430 431 def gravitationalSystemImage(self): 432 """ 433 layout and initialization data 434 """ 435 ########################## 436 # layout of current page # 437 ########################## 438 self.currentImage = "gravitationalSystemImage" 439 self.controlClear() 440 441 layout = QGridLayout() 442 layout.setSpacing(10) 443 444 text = ['长度单位', '时间单位', '质量单位', '电量单位', 445 '质点类型', '质点个数', '动画时长', '总帧数', '播放速率', 446 '坐标轴标签', '视角', '速度矢量', '加速度矢量'] 447 position = [[0, 0, 1, 1], [0, 1, 1, 1], [0, 2, 1, 1], [0, 3, 1, 1], 448 [0, 4, 1, 1], [0, 5, 1, 1], [0, 6, 1, 1], [2, 0, 1, 1], [2, 1, 1, 1], 449 [2, 2, 1, 1], [2, 3, 1, 1], [2, 4, 1, 1], [2, 5, 1, 1]] 450 self.controlLayout(layout=layout, name="QLabel", var={"text": text}, position=position, signal=None) 451 452 itemText = [['ly', 'km', 'm', 'mm', 'nm'], ['year', 'day', 's', 'ms', 'μs'], 453 ['kg', '太阳(1.99+e30kg)', '质子(1.7-e27kg)', '电子(9.1-e31kg)'], ['C', 'e(1.6-e19C)'], 454 ['天体-天体', '电荷-电荷', '自定义-自定义'], list(map(str, range(2, 10))), 455 list(map(str, range(5, 65, 5))), ['100', '1000', '10000', '100000'], 456 ['显示', '隐藏'], ['静止', '旋转'], ['隐藏速度矢量', '显示当前速度矢量', '显示所有速度矢量'], 457 ['隐藏加速度矢量', '显示当前加速度矢量', '显示所有加速度矢量']] 458 currentIndex = [2, 2, 0, 0, 2, 1, 2, 2, 0, 1, 1, 1] 459 position = [[1, 0, 1, 1], [1, 1, 1, 1], [1, 2, 1, 1], [1, 3, 1, 1], 460 [1, 4, 1, 1], [1, 5, 1, 1], [1, 6, 1, 1], [3, 0, 1, 1], 461 [3, 2, 1, 1], [3, 3, 1, 1], [3, 4, 1, 1], [3, 5, 1, 1]] 462 self.controlLayout(layout=layout, name="QComboBox", var={"itemText": itemText, "currentIndex": currentIndex}, 463 position=position, signal=self.gravitationalSystemImageSignal) 464 465 var = {"range": [[1, 1000]], "singleStep": [1], "prefix": ['X '], "suffix": [" 倍"], "value": [100]} 466 position = [[3, 1, 1, 1]] 467 self.controlLayout(layout=layout, name="QSpinBox", var=var, 468 position=position, signal=self.gravitationalSystemImageSignal) 469 470 text = ['启用调试单位'] 471 isChecked = [True] 472 position = [[2, 6, 1, 1]] 473 self.controlLayout(layout=layout, name="QRadioButton", var={"text": text, "isChecked": isChecked}, 474 position=position, signal=self.gravitationalSystemImageSignal) 475 476 text = ['播放动画'] 477 position = [[3, 6, 1, 1]] 478 self.controlLayout(layout=layout, name="QPushButton", var={"text": text}, 479 position=position, signal=self.gravitationalSystemImageDraw) 480 481 # noinspection PyArgumentList 482 widget = [[QWidget(), QWidget()]] 483 name = ["QTableWidget", "QTextEdit"] 484 var = [{"headerLabels": [["mass", "electricity", "X-coordinate", "Y-coordinate", "Z-coordinate", 485 "X-velocity", "Y-velocity", "Z-velocity"]], 486 "data": [numpy.array([[1, 0, 1, 0, 0, 0, 1, 0], 487 [1, 1, 0, 1, 0, 0, 0, 1], 488 [1, -1, 0, 0, 1, 1, 0, 0]])]}, 489 {"text": [["yes", "no"]]}] 490 for j in range(0, 2): 491 widgetLayout = QGridLayout() 492 position = [[0, 0, 1, 1]] 493 self.controlLayout(layout=widgetLayout, name=name[j], var=var[j], position=position, signal=None) 494 widget[0][j].setLayout(widgetLayout) 495 text = [["Initial Condition", "Note"]] 496 position = [[4, 0, 1, 7]] 497 self.controlLayout(layout=layout, name="QTabWidget", var={"text": text, "widget": widget}, 498 position=position, signal=None) 499 500 # noinspection PyArgumentList 501 widget = QWidget() 502 widget.setLayout(layout) 503 self.setCentralWidget(widget) 504 505 ############################################################################### 506 # initialization self.controlData["gravitationalSystemImage"] then refresh it # 507 # refresh self.control["gravitationalSystemImage"] # 508 ############################################################################### 509 if "gravitationalSystemImage" not in self.controlData: 510 self.addFrame("gravitationalSystemImage") 511 self.gravitationalSystemImageSignal() 512 else: 513 for j in range(0, len(self.control["QComboBox"])): 514 self.control["QComboBox"][j].currentIndexChanged.disconnect(self.gravitationalSystemImageSignal) 515 for j in range(0, len(self.control["QSpinBox"])): 516 self.control["QSpinBox"][j].valueChanged.disconnect(self.gravitationalSystemImageSignal) 517 for j in range(0, len(self.control["QRadioButton"])): 518 self.control["QRadioButton"][j].clicked.disconnect(self.gravitationalSystemImageSignal) 519 self.imageRead(imageName="gravitationalSystemImage") 520 for j in range(0, len(self.control["QComboBox"])): 521 self.control["QComboBox"][j].currentIndexChanged.connect(self.gravitationalSystemImageSignal) 522 for j in range(0, len(self.control["QSpinBox"])): 523 self.control["QSpinBox"][j].valueChanged.connect(self.gravitationalSystemImageSignal) 524 for j in range(0, len(self.control["QRadioButton"])): 525 self.control["QRadioButton"][j].clicked.connect(self.gravitationalSystemImageSignal) 526 527 self.statusBar().showMessage('Ready') 528 529 def gravitationalSystemImageSignal(self): 530 """ 531 respond of current page(gravitationalSystemImage), then write data into MainData.dataClasses 532 """ 533 self.statusBar().showMessage('Saving Page data...') 534 535 ############################################################### 536 # initialization self.controlData["gravitationalSystemImage"] # 537 ############################################################### 538 imageName = "gravitationalSystemImage" 539 self.controlDataClear(imageName) 540 541 ######################################################## 542 # refresh self.controlData["gravitationalSystemImage"] # 543 ######################################################## 544 for j in range(0, len(self.control["QComboBox"])): 545 itemText = list() 546 for k in range(0, self.control["QComboBox"][j].count()): 547 itemText.append(self.control["QComboBox"][j].itemText(k)) 548 self.controlData[imageName]["QComboBox"]["itemText"].append(itemText) 549 550 currentIndex = self.control["QComboBox"][j].currentIndex() 551 self.controlData[imageName]["QComboBox"]["currentIndex"].append(currentIndex) 552 553 for i in range(0, len(self.control["QTableWidget"])): 554 currentRow = self.control["QTableWidget"][i].rowCount() 555 row = int(self.control["QComboBox"][5].currentText()) 556 column = self.control["QTableWidget"][i].columnCount() 557 data = numpy.zeros((row, column), dtype=numpy.float64) 558 for j in range(0, row): 559 for k in range(0, column): 560 if j < currentRow: 561 # noinspection PyBroadException 562 try: 563 data[j][k] = float(self.control["QTableWidget"][i].item(j, k).text()) 564 except: 565 data[j][k] = 0 566 self.controlData[imageName]["QTableWidget"]["data"].append(data) 567 568 for j in range(0, len(self.control["QSpinBox"])): 569 value = self.control["QSpinBox"][j].value() 570 self.controlData[imageName]["QSpinBox"]["value"].append(value) 571 572 for j in range(0, len(self.control["QRadioButton"])): 573 isChecked = self.control["QRadioButton"][j].isChecked() 574 self.controlData[imageName]["QRadioButton"]["isChecked"].append(isChecked) 575 576 #################################################### 577 # refresh self.control["gravitationalSystemImage"] # 578 #################################################### 579 for j in range(0, len(self.control["QComboBox"])): 580 self.control["QComboBox"][j].currentIndexChanged.disconnect(self.gravitationalSystemImageSignal) 581 for j in range(0, len(self.control["QSpinBox"])): 582 self.control["QSpinBox"][j].valueChanged.disconnect(self.gravitationalSystemImageSignal) 583 for j in range(0, len(self.control["QRadioButton"])): 584 self.control["QRadioButton"][j].clicked.disconnect(self.gravitationalSystemImageSignal) 585 self.imageRead(imageName="gravitationalSystemImage") 586 for j in range(0, len(self.control["QComboBox"])): 587 self.control["QComboBox"][j].currentIndexChanged.connect(self.gravitationalSystemImageSignal) 588 for j in range(0, len(self.control["QSpinBox"])): 589 self.control["QSpinBox"][j].valueChanged.connect(self.gravitationalSystemImageSignal) 590 for j in range(0, len(self.control["QRadioButton"])): 591 self.control["QRadioButton"][j].clicked.connect(self.gravitationalSystemImageSignal) 592 593 self.statusBar().showMessage('Page data Saved.') 594 595 def gravitationalSystemImageDraw(self): 596 """ 597 Draw animation of solution of ordinary differential equations 598 """ 599 ######################################################## 600 # refresh self.controlData["gravitationalSystemImage"] # 601 ######################################################## 602 self.gravitationalSystemImageSignal() 603 self.statusBar().showMessage('Start to solving the ordinary differential equations...') 604 605 ##################################################### 606 # get parameters of ordinary differential equations # 607 ##################################################### 608 imageName = "gravitationalSystemImage" 609 aniArg = self.controlData[imageName]["QComboBox"]["currentIndex"][8:] 610 611 data = self.controlData[imageName]["QTableWidget"]["data"][0] 612 mass = data[:, 0] 613 for j in range(0, len(mass)): 614 if mass[j] < 0 or mass[j] == 0: 615 self.statusBar().showMessage('mass[%d] must be positive.' % j) 616 return 617 618 electric = numpy.abs(data[:, 1]) 619 620 electricType = numpy.sign(data[:, 1]) 621 622 cood = data[:, 2:5] 623 coodCheck = numpy.dot(cood, cood.T) 624 for j in range(0, len(mass)): 625 for k in range(j, len(mass)): 626 if (coodCheck[j, j] + coodCheck[k, k]) == 2 * coodCheck[j, k] and j != k: 627 self.statusBar().showMessage('point[%d] and point[%d] share the same coordinate.' % (j, k)) 628 return 629 630 vel = data[:, 5:] 631 632 if self.controlData[imageName]["QRadioButton"]["isChecked"][0]: 633 GUnit = 1 634 KUnit = 1 635 else: 636 lenUnitMap = {0: 9.46 * 10 ** 15, 1: 1000, 2: 1, 3: 0.001, 4: 10 ** (-9)} 637 lenUnit = lenUnitMap[self.controlData[imageName]["QComboBox"]["currentIndex"][0]] 638 639 timeUnitMap = {0: 3.1536 * 10 ** 7, 1: 86400, 2: 1, 3: 0.001, 4: 10 ** (-6)} 640 timeUnit = timeUnitMap[self.controlData[imageName]["QComboBox"]["currentIndex"][1]] 641 642 massUnitMap = {0: 1, 1: 1.99 * 10 ** 30, 2: 1.7 * 10 ** (-27), 3: 9.1 * 10 ** (-31)} 643 massUnit = massUnitMap[self.controlData[imageName]["QComboBox"]["currentIndex"][2]] 644 645 electricUnitMap = {0: 1, 1: 1.6 * 10 ** (-19)} 646 electricUnit = electricUnitMap[self.controlData[imageName]["QComboBox"]["currentIndex"][3]] 647 648 GUnit = 6.67408 * 10 ** (-11) * massUnit * timeUnit ** 2 / lenUnit ** 3 649 KUnit = 8.987 * 10 ** 9 * electricUnit ** 2 * timeUnit ** 2 / lenUnit ** 3 / massUnit 650 651 timeLength = int(self.control["QComboBox"][6].currentText()) 652 nodeNumber = int(self.control["QComboBox"][7].currentText()) 653 t = numpy.arange(0, timeLength, timeLength / nodeNumber) 654 655 aniSpeed = self.controlData[imageName]["QSpinBox"]["value"][0] 656 657 ######################################################## 658 # draw the solution of ordinary differential equations # 659 ######################################################## 660 self.controlClear() 661 662 layout = QGridLayout() 663 layout.setSpacing(10) 664 665 # noinspection PyArgumentList 666 widget = QWidget() 667 self.canvas["gravitationalSystemImage"] = GravitationCanvas(aniArg, mass, electric, electricType, cood, vel, 668 GUnit, KUnit, t, aniSpeed, parent=widget) 669 self.controlData[imageName]["save"] = [mass, electric, electricType, cood, vel, GUnit, KUnit, t, 670 self.canvas["gravitationalSystemImage"].track, 671 self.canvas["gravitationalSystemImage"].vector, 672 self.canvas["gravitationalSystemImage"].acc] 673 674 layout.addWidget(self.canvas["gravitationalSystemImage"]) 675 widget.setLayout(layout) 676 self.setCentralWidget(widget) 677 678 self.statusBar().showMessage('Ready') 679 680 def convexHullImage(self): 681 """ 682 layout and initialization data 683 """ 684 ########################## 685 # layout of current page # 686 ########################## 687 self.currentImage = "convexHullImage" 688 self.controlClear() 689 690 layout = QGridLayout() 691 layout.setSpacing(10) 692 693 text = ['空间维数', '散点个数', '查看迭代步数'] 694 position = [[0, 0, 1, 1], [0, 2, 1, 1], [0, 4, 1, 1]] 695 self.controlLayout(layout=layout, name="QLabel", var={"text": text}, position=position, signal=None) 696 697 itemText = [list(map(str, range(2, 15))), list(map(str, range(3, 50))), 698 ["-complete-"] + list(map(str, range(1, 9)))] 699 currentIndex = [1, 6, 0] 700 position = [[0, 1, 1, 1], [0, 3, 1, 1], [0, 5, 1, 1]] 701 self.controlLayout(layout=layout, name="QComboBox", var={"itemText": itemText, "currentIndex": currentIndex}, 702 position=position, signal=self.convexHullImageSignal) 703 704 text = ['随机生成散点集'] 705 position = [[0, 6, 1, 1]] 706 self.controlLayout(layout=layout, name="QPushButton", var={"text": text}, 707 position=position, signal=self.convexHullImageRandom) 708 709 # noinspection PyArgumentList 710 widget = [[QWidget(), QWidget(), QWidget()]] 711 matrixLayout = QGridLayout() 712 matrix = [numpy.array([[6, 0, 9, 9, 6, 6, 2, 0, 6], 713 [5, 7, 2, 6, 7, 3, 7, 4, 4], 714 [8, 3, 2, 5, 0, 0, 7, 6, 5]])] 715 self.controlLayout(layout=matrixLayout, name="QTableWidget", var={"headerLabels": [], "data": matrix}, 716 position=[[0, 0, 1, 1]], signal=None) 717 widget[0][0].setLayout(matrixLayout) 718 719 patches_listLayout = QGridLayout() 720 patches_list = [numpy.array([[4, 2, 6, 0, 1, 1, 0, 0, 2, 5, 5, 5], 721 [6, 4, 0, 6, 6, 7, 2, 7, 5, 2, 1, 7], 722 [3, 3, 3, 7, 4, 6, 3, 2, 4, 7, 4, 1]])] 723 self.controlLayout(layout=patches_listLayout, name="QTableWidget", 724 var={"headerLabels": [], "data": patches_list}, position=[[0, 0, 1, 1]], signal=None) 725 widget[0][1].setLayout(patches_listLayout) 726 727 canvasLayout = QGridLayout() 728 self.canvas["convexHullImage"] = ConvexHullCanvas(matrix[0], patches_list, parent=widget[0][2]) 729 canvasLayout.addWidget(self.canvas["convexHullImage"]) 730 widget[0][2].setLayout(canvasLayout) 731 732 text = [["Points", "Patches", "Convex Hull 3D"]] 733 position = [[1, 0, 1, 7]] 734 self.controlLayout(layout=layout, name="QTabWidget", var={"text": text, "widget": widget}, 735 position=position, signal=None) 736 737 # noinspection PyArgumentList 738 widget = QWidget() 739 widget.setLayout(layout) 740 self.setCentralWidget(widget) 741 742 ###################################################################### 743 # initialization self.controlData["convexHullImage"] then refresh it # 744 # refresh self.control["convexHullImage"] # 745 ###################################################################### 746 if "convexHullImage" not in self.controlData: 747 self.addFrame("convexHullImage") 748 self.convexHullImageSignal() 749 else: 750 for j in range(0, len(self.control["QComboBox"])): 751 self.control["QComboBox"][j].currentIndexChanged.disconnect(self.convexHullImageSignal) 752 self.imageRead(imageName="convexHullImage") 753 for j in range(0, len(self.control["QComboBox"])): 754 self.control["QComboBox"][j].currentIndexChanged.connect(self.convexHullImageSignal) 755 756 self.statusBar().showMessage('Ready') 757 758 def convexHullImageSignal(self): 759 """ 760 respond of current page(convexHullImage), then write data into MainData.controlData 761 """ 762 self.statusBar().showMessage('Setting patches...') 763 764 ###################################################### 765 # initialization self.controlData["convexHullImage"] # 766 ###################################################### 767 imageName = "convexHullImage" 768 self.controlDataClear(imageName) 769 770 ############################################### 771 # refresh self.controlData["convexHullImage"] # 772 ############################################### 773 m = int(self.control["QComboBox"][0].itemText(self.control["QComboBox"][0].currentIndex())) 774 n = int(self.control["QComboBox"][1].itemText(self.control["QComboBox"][1].currentIndex())) 775 if m < n: 776 pass 777 else: 778 self.statusBar().showMessage('The number of points should be more than dimension.') 779 return 780 781 list(map(str, range(4, 50))) 782 for j in range(0, len(self.control["QComboBox"])): 783 itemText = list() 784 for k in range(0, self.control["QComboBox"][j].count()): 785 itemText.append(self.control["QComboBox"][j].itemText(k)) 786 self.controlData[imageName]["QComboBox"]["itemText"].append(itemText) 787 788 currentIndex = self.control["QComboBox"][j].currentIndex() 789 self.controlData[imageName]["QComboBox"]["currentIndex"].append(currentIndex) 790 791 row = int(self.control["QComboBox"][0].currentText()) 792 column = int(self.control["QComboBox"][1].currentText()) 793 currentRow = self.control["QTableWidget"][0].rowCount() 794 currentColumn = self.control["QTableWidget"][0].columnCount() 795 matrix = numpy.zeros((row, column), dtype=numpy.float64) 796 for j in range(0, row): 797 for k in range(0, column): 798 if j < currentRow and k < currentColumn: 799 # noinspection PyBroadException 800 try: 801 matrix[j][k] = float(self.control["QTableWidget"][0].item(j, k).text()) 802 except: 803 matrix[j][k] = 0 804 self.controlData[imageName]["QTableWidget"]["data"].append(matrix) 805 806 obj = ConvexHullMap(matrix=matrix) 807 obj.complete() 808 patches = numpy.array(obj.patches).T 809 self.controlData[imageName]["QTableWidget"]["data"].append(patches) 810 811 self.controlData[imageName]["save"] = [matrix, patches] 812 813 ############## 814 # draw image # 815 ############## 816 if int(self.control["QComboBox"][0].currentText()) == 3: 817 self.canvas[imageName].canvasData["matrix"] = matrix 818 if self.control["QComboBox"][2].currentIndex() == 0: 819 self.canvas[imageName].canvasData["patches_list"] = [obj.patches] 820 else: 821 new_obj = ConvexHullMap(matrix=matrix) 822 self.canvas[imageName].canvasData["patches_list"] = [copy.deepcopy(new_obj.patches)] 823 for j in range(0, int(self.control["QComboBox"][2].currentText())): 824 new_obj.classify_points() 825 if new_obj.next_points.count(None) == len(new_obj.next_points): 826 break 827 new_obj.expand_patches() 828 self.canvas[imageName].canvasData["patches_list"].append(copy.deepcopy(new_obj.patches)) 829 self.canvas[imageName].fig.clf() 830 self.canvas[imageName].axes = axes3d.Axes3D(self.canvas[imageName].fig) 831 self.canvas[imageName].complete_draw() 832 self.canvas[imageName].fig.canvas.draw() 833 834 ########################################### 835 # refresh self.control["convexHullImage"] # 836 ########################################### 837 for j in range(0, len(self.control["QComboBox"])): 838 self.control["QComboBox"][j].currentIndexChanged.disconnect(self.convexHullImageSignal) 839 self.imageRead(imageName=imageName) 840 for j in range(0, len(self.control["QComboBox"])): 841 self.control["QComboBox"][j].currentIndexChanged.connect(self.convexHullImageSignal) 842 843 self.statusBar().showMessage('End of setting title.') 844 845 def convexHullImageRandom(self): 846 """ 847 Reset coordinates of scattered point set 848 """ 849 ############################################### 850 # refresh self.controlData["convexHullImage"] # 851 ############################################### 852 self.statusBar().showMessage('Start to resetting coordinates of scattered points...') 853 854 ######################################### 855 # get parameters of scattered point set # 856 ######################################### 857 imageName = "convexHullImage" 858 859 n = int(self.control["QComboBox"][0].currentText()) 860 m = int(self.control["QComboBox"][1].currentText()) 861 matrix = numpy.random.random_integers(low=0, high=10, size=(n, m)) 862 self.controlData[imageName]["QTableWidget"]["data"][0] = matrix 863 self.controlData[imageName]["save"][0] = matrix 864 865 self.imageRead(imageName=imageName) 866 867 self.convexHullImageSignal() 868 869 self.statusBar().showMessage('End of resetting coordinates of scattered points.') 870 871 def analyticFunctionImage(self): 872 """ 873 layout and initialization data 874 """ 875 ########################## 876 # layout of current page # 877 ########################## 878 self.currentImage = "analyticFunctionImage" 879 self.controlClear() 880 881 layout = QGridLayout() 882 layout.setSpacing(10) 883 884 text = ['次方数', '拉伸系数', '辐角'] 885 position = [[0, 0, 1, 1], [0, 2, 1, 1], [0, 4, 1, 1]] 886 self.controlLayout(layout=layout, name="QLabel", var={"text": text}, position=position, signal=None) 887 888 itemText = [list(map(str, range(1, 20)))] 889 position = [[0, 1, 1, 1]] 890 self.controlLayout(layout=layout, name="QComboBox", var={"itemText": itemText, "currentIndex": []}, 891 position=position, signal=self.analyticFunctionImageSignal) 892 893 var = {"range": [[1, 100], [-180, 180]], "singleStep": [1, 1], 894 "prefix": [], "suffix": ['*0.1', '*pi/180'], "value": [10, 0]} 895 position = [[0, 3, 1, 1], [0, 5, 1, 1]] 896 self.controlLayout(layout=layout, name="QSpinBox", var=var, 897 position=position, signal=self.analyticFunctionImageSignal) 898 899 text = [['%f*e**(i*%f)*z**%d + z = 1' % (1, 1, 0)]] 900 # noinspection PyArgumentList 901 widget = [[QWidget()]] 902 position = [[1, 0, 1, 6]] 903 widgetLayout = QGridLayout() 904 self.canvas["analyticFunctionImage"] = AnalyticFunctionCanvas(1, 1, 0, parent=widget[0][0]) 905 widgetLayout.addWidget(self.canvas["analyticFunctionImage"]) 906 widget[0][0].setLayout(widgetLayout) 907 self.controlLayout(layout=layout, name="QTabWidget", var={"text": text, "widget": widget}, 908 position=position, signal=None) 909 910 # noinspection PyArgumentList 911 widget = QWidget() 912 widget.setLayout(layout) 913 self.setCentralWidget(widget) 914 915 ############################################################################ 916 # initialization self.controlData["analyticFunctionImage"] then refresh it # 917 # refresh self.control["analyticFunctionImage"] # 918 ############################################################################ 919 if "analyticFunctionImage" not in self.controlData: 920 self.addFrame("analyticFunctionImage") 921 self.analyticFunctionImageSignal() 922 else: 923 for j in range(0, len(self.control["QComboBox"])): 924 self.control["QComboBox"][j].currentIndexChanged.disconnect(self.analyticFunctionImageSignal) 925 for j in range(0, len(self.control["QSpinBox"])): 926 self.control["QSpinBox"][j].valueChanged.disconnect(self.analyticFunctionImageSignal) 927 self.imageRead(imageName="analyticFunctionImage") 928 for j in range(0, len(self.control["QComboBox"])): 929 self.control["QComboBox"][j].currentIndexChanged.connect(self.analyticFunctionImageSignal) 930 for j in range(0, len(self.control["QSpinBox"])): 931 self.control["QSpinBox"][j].valueChanged.disconnect(self.analyticFunctionImageSignal) 932 933 self.statusBar().showMessage('Ready') 934 935 def analyticFunctionImageSignal(self): 936 """ 937 respond of current page(analyticFunctionImage), then write data into MainData.controlData 938 """ 939 self.statusBar().showMessage('Starting draw image...') 940 941 ############################################################ 942 # initialization self.controlData["analyticFunctionImage"] # 943 ############################################################ 944 imageName = "analyticFunctionImage" 945 self.controlDataClear(imageName) 946 947 ##################################################### 948 # refresh self.controlData["analyticFunctionImage"] # 949 ##################################################### 950 for j in range(0, len(self.control["QComboBox"])): 951 itemText = list() 952 for k in range(0, self.control["QComboBox"][j].count()): 953 itemText.append(self.control["QComboBox"][j].itemText(k)) 954 self.controlData[imageName]["QComboBox"]["itemText"].append(itemText) 955 956 currentIndex = self.control["QComboBox"][j].currentIndex() 957 self.controlData[imageName]["QComboBox"]["currentIndex"].append(currentIndex) 958 959 for j in range(0, len(self.control["QSpinBox"])): 960 value = self.control["QSpinBox"][j].value() 961 self.controlData[imageName]["QSpinBox"]["value"].append(value) 962 963 ############## 964 # draw image # 965 ############## 966 self.canvas[imageName].n = self.controlData[imageName]["QComboBox"]["currentIndex"][0] + 1 967 self.canvas[imageName].r = self.controlData[imageName]["QSpinBox"]["value"][0] * 0.1 968 self.canvas[imageName].t = self.controlData[imageName]["QSpinBox"]["value"][1] * math.pi / 180 969 text = '%f*e**(i*%f)*z**%d + z = 1' % (self.canvas[imageName].n, self.canvas[imageName].r, 970 self.canvas[imageName].t) 971 self.control["QTabWidget"][0].setTabText(0, text) 972 self.canvas[imageName].fig.clf() 973 self.canvas[imageName].axes = self.canvas[imageName].fig.add_subplot(111) 974 self.canvas[imageName].axes.grid(True) 975 self.canvas[imageName].complete_draw() 976 self.canvas[imageName].fig.canvas.draw() 977 978 ################################################ 979 # refresh self.control["analyticFunctionImage"] # 980 ################################################ 981 for j in range(0, len(self.control["QComboBox"])): 982 self.control["QComboBox"][j].currentIndexChanged.disconnect(self.analyticFunctionImageSignal) 983 self.imageRead(imageName=imageName) 984 for j in range(0, len(self.control["QComboBox"])): 985 self.control["QComboBox"][j].currentIndexChanged.connect(self.analyticFunctionImageSignal) 986 987 self.statusBar().showMessage('Image is drawn.') 988 989 @staticmethod 990 def sourceCodeImage(): 991 """ 992 @ 993 """ 994 pass 995 996 def keyPressEvent(self, event): 997 """ 998 :param event: 999 :return: 1000 """ 1001 if event.key() == Qt.Key_Escape: 1002 try: 1003 if self.currentImage == "rainImage": 1004 self.orthogonalTableImage() 1005 elif self.currentImage == "orthogonalTableImage": 1006 pass 1007 elif self.currentImage == "convexHullImage": 1008 pass 1009 elif self.currentImage == "gravitationalSystemImage": 1010 self.gravitationalSystemImage() 1011 elif self.currentImage == "analyticFunctionImage": 1012 pass 1013 except KeyError: 1014 self.startImage() 1015 self.statusBar().showMessage('Esc is pressed!') 1016 1017 def showOpenDialog(self): 1018 """ 1019 @ 1020 """ 1021 # noinspection PyCallByClass,SpellCheckingInspection 1022 fname = QFileDialog.getOpenFileName(self, 'Open file', '/home') 1023 1024 # if fname[0]: 1025 # # noinspection PyArgumentEqualDefault 1026 # f = open(fname[0], 'r') 1027 # with f: 1028 # data = f.read() 1029 # self.textEdit.setText(data) 1030 1031 def buttonClicked(self): 1032 """ 1033 @ 1034 """ 1035 sender = self.sender() 1036 self.statusBar().showMessage(sender.text() + ' was pressed') 1037 # noinspection PyCallByClass,PyTypeChecker 1038 QInputDialog.getText(self, 'Input Dialog', 'Enter your name:') 1039 1040 def closeEvent(self, event): 1041 """ 1042 @ 1043 """ 1044 # noinspection PyCallByClass,PyTypeChecker 1045 reply = QMessageBox.question(self, 'Message', "Are you sure to quit?", 1046 QMessageBox.Yes | QMessageBox.No, QMessageBox.No) 1047 if reply == QMessageBox.Yes: 1048 event.accept() 1049 else: 1050 event.ignore()
功能展示
开始界面:
正交试验表页面:
凸包页面:
常微分方程组页面:
目前为止只制作了4个模块,后续我在博客里每多写一篇理论性的文章的时候,都会添加图形演示至本文章。
声明
本文由“Hamilton算符”原创,未经博主允许不得转载!