概述
目前有关于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/pythonMainData
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/pythonMainWindow
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算符”原创,未经博主允许不得转载!