class CategoryMetrics(QHBoxLayout): def __init__(self, state, data): super().__init__() self.state = state self.data = data self.createPlot() def createPlot(self): fig = Figure(dpi=72, facecolor=(1, 1, 1), edgecolor=(0, 0, 0)) self.axis = fig.add_subplot(111) self.canvas = FigureCanvas(fig) amounts, labels = self.parseData(self.data) self.axis.pie(amounts, labels=labels, shadow=True) self.addWidget(self.canvas) def parseData(self, data): categoryList = self.getCategorieslist() labels = list(categoryList.keys()) labels = ['{} (${:.0f})'.format(k, categoryList[k]) for k in labels] totalAmount = sum(list(categoryList.values())) proportionalCategories = [ a / totalAmount for a in list(categoryList.values()) ] return proportionalCategories, labels def getCategorieslist(self): config = self.state.getConfig() months = sorted(list(self.data.keys())) categories = {} for month in months: monthTransactions = self.data[month] monthCat = list(config['months'][month].keys()) for category in monthCat: tList = config['months'][month][category]['transactionList'] if category == 'Income': continue # categorySum = sum(map(lambda t: t.isCredit and t.amt or 0, monthTransactions)) else: categorySum = sum( map(lambda t: t.name in tList and t.amt or 0, monthTransactions)) if category in categories: categories[category] += categorySum else: categories[category] = categorySum return categories def updateData(self, data): self.data = data self.canvas.deleteLater() self.createPlot()
def deleteLater(self, *args): self.delete() return FigureCanvasQTAgg.deleteLater(self, *args)
def deleteLater(self, *args): self.delete() return FigureCanvasQTAgg.deleteLater(self, *args)
class MainWindow(QtGui.QMainWindow, design.Ui_MainWindow): """ This Class's functions draw figures on GUI and do tasks with GUI """ def __init__(self): super(self.__class__, self).__init__() self.setupUi(self) self.btn_start.clicked.connect(self.renderButtonClicked) self.btn_play_pause.clicked.connect(self.play) self.btn_stop.clicked.connect(self.stop) self.resize(1500, 1100) def renderButtonClicked(self): ''' What do when Start Button is clicked ''' # Change GUI Components QApplication.processEvents() self.btn_start.setEnabled(False) # FROM HIER: RUN IN NEW THREAD self.get_thread = DrawGraphThread() self.get_thread.start() # New Thread started self.drawFigure() def drawFigure(self): ''' Draw first figure on GUI and wait the FigureList to be filled, so it could draw another Figure :return: ''' global FigureList self.frameNumber = 0 # Start rendering with frame 0 # Wait FigureList to fill the first Figure while len(FigureList) <= self.frameNumber: print('waiting for FigureList to init') time.sleep(.200) #First Figure Initialized thisFigure = FigureList[self.frameNumber] self.dynamic_canvas = FigureCanvas(thisFigure) self.view_layout.addWidget(self.dynamic_canvas) self.view_layout.removeWidget(self.dynamic_canvas) #Loop to update Figures self._timer = self.dynamic_canvas.new_timer(100, callbacks=[ (self.updateFigure, [], {}) ]) self._timer.start() def updateFigure(self): ''' Update the Figure. When the a figure need to draw but still not in the FigureList, it wait with a for-loop :return: ''' # Update Progess bar if self.progress_bar.value() != 100: self.progress_bar.setValue( float((len(FigureList) / NumberOfFramesWouldBeRendered)) * 100) # Add new Frame self.view_layout.addWidget(self.view_graph) self.dynamic_canvas.setParent(None) figure = copy.copy(FigureList[len(FigureList) - 1]) # prevent figure to zoom in self.dynamic_canvas = FigureCanvas(figure) self.view_layout.addWidget(self.dynamic_canvas) self.view_layout.removeWidget(self.dynamic_canvas) self.label_status.setText("Rendering " + str(self.progress_bar.value()) + '% done') else: # All Frames are rendered self._timer.stop() self.btn_play_pause.setEnabled(True) self.btn_stop.setEnabled(True) self.progress_bar.hide() self.dynamic_canvas.setParent(None) self.label_status.setText("Rendering is finished.") def play(self): ''' Play rendered Frames ''' # Update UI self.btn_play_pause.setEnabled(False) self.btn_stop.setEnabled(True) self.label_status.hide() self.frameNumber = 0 self._timer2 = self.dynamic_canvas.new_timer( 100, callbacks=[(self.updateFigurePlayback, [], {})]) self._timer2.start() def stop(self): ''' Stop playing ''' self._timer2.stop() def updateFigurePlayback(self): ''' Update the Figure. When the a figure need to draw but still not in the FigureList, it wait with a for-loop :return: ''' # The Graph will stop at last Frame if self.frameNumber >= NumberOfFramesWouldBeRendered - 1: self._timer.stop() else: # Not at last Frame self.view_graph.setParent(None) self.view_layout.removeWidget(self.label_status) if self.frameNumber != 0: self.view_layout.removeWidget(self.dynamic_canvas) self.dynamic_canvas.deleteLater() self.frameNumber = self.frameNumber + 1 figure = FigureList[self.frameNumber] self.dynamic_canvas = FigureCanvas(figure) self.view_layout.addWidget(self.dynamic_canvas) def closeEvent(self, event): sys.exit(app.exec_())