概述
目前有關於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算符”原創,未經博主允許不得轉載!