def create_piechart(self, series, animation=True): if animation: animation_type = QChart.AllAnimations else: animation_type = QChart.NoAnimation font_title = QFont() font_title.setBold(True) font_title.setPointSize(13) # define the chart properties chart = QChart() chart.addSeries(series) chart.createDefaultAxes() chart.setAnimationOptions(animation_type) chart.setBackgroundVisible(False) chart.setMargins(QMargins()) chart.setTitle("Prediction Distribution") chart.setTitleFont(font_title) font_legend = QFont() font_legend.setBold(True) # define legend properties chart.legend().show() chart.legend().setVisible(True) chart.legend().setAlignment(Qt.AlignBottom) chart.legend().setFont(font_legend) self.ui.piechart.setChart(chart) self.ui.piechart.setRenderHint(QPainter.Antialiasing) QApplication.processEvents()
def create_barchart(self, series, max_val, animation=True): if animation: animation_type = QChart.AllAnimations else: animation_type = QChart.NoAnimation chart = QChart() chart.addSeries(series) chart.setBackgroundVisible(False) chart.setMargins(QMargins()) chart.setAnimationOptions(animation_type) labels = ('Human', 'Bot') axisX = QBarCategoryAxis() axisX.append(labels) axisY = QValueAxis() axisY.setTitleText("Percentage (%)") axisY.setRange(0, max_val) chart.addAxis(axisX, Qt.AlignBottom) chart.addAxis(axisY, Qt.AlignLeft) font = QFont() font.setPointSize(9) chart.legend().setVisible(True) chart.legend().setFont(font) chart.legend().setAlignment(Qt.AlignBottom) self.ui.barchart.setChart(chart) self.ui.barchart.setRenderHint(QPainter.Antialiasing)
def plot_candlechart(ohlc_data): app = ParaMakerApplication([]) #app.setStyleSheet("background-color:black;") series = QCandlestickSeries() series.setBodyOutlineVisible(False) series.setDecreasingColor(Qt.red) series.setIncreasingColor(Qt.green) rsi = qc.QLineSeries() # 5-days average data line rsi.append(QPointF(ohlc_data[300].timestamp, ohlc_data[300].closed)) rsi.append(QPointF(ohlc_data[700].timestamp, ohlc_data[700].closed)) #rsi.append(QPointF(ohlc_data[150].timestamp, ohlc_data[100].closed)) tm = [] # stores str type data # in a loop, series and rsi append corresponding data for candle in ohlc_data: series.append( QCandlestickSet(candle.opened, candle.high, candle.low, candle.closed)) #rsi.append(QPointF(num, m)) tm.append(str(candle.timestamp)) #rsi.append(str(candle.timestamp)) #rsi_values = calculate_rsi(14, ohlc_data) chart = QChart() chart.setBackgroundVisible(False) chart.setPlotAreaBackgroundVisible(False) chart.addSeries(series) # candle chart.addSeries(rsi) # rsi line #chart.axisX(rsi).setRange(ohlc_data[0].timestamp, ohlc_data[-1].timestamp) chart.createDefaultAxes() axisXRSI = QValueAxis() axisYRSI = QValueAxis() axisXRSI.setRange(ohlc_data[0].timestamp, ohlc_data[-1].timestamp) axisYRSI.setRange(ohlc_data[0].closed, ohlc_data[-1].closed) axisXRSI.setGridLineVisible(False) axisYRSI.setGridLineVisible(False) chart.setAxisX(axisXRSI, rsi) chart.setAxisY(axisYRSI, rsi) chart.legend().hide() chart.axisX(series).setCategories(tm) #chart.axisX(series).setGridLineVisible(False) #chart.axisY(series).setGridLineVisible(False) ###chart.axisX(rsi).setVisible(False) chartview = QChartView(chart) chartview.setRenderHint(QPainter.Antialiasing) ui = ParaMakerWindow() ui.setCentralWidget(chartview) sys.exit(app.exec_())
class pieChartView(QChartView): def __init__(self, *args, **kwargs): super(pieChartView, self).__init__(*args, **kwargs) self.initChart() self.refresh() def initChart(self): self._chart = QChart() # 调整边距 self._chart.layout().setContentsMargins(0, 0, 0, 0) # 外界 self._chart.setMargins(QMargins(3, 0, 3, 0)) # 内界 self._chart.setBackgroundRoundness(0) self._chart.setBackgroundVisible(False) # 设置主题 self._chart.setTheme(QChart.ChartThemeBlueIcy) # 抗锯齿 self.setRenderHint(QPainter.Antialiasing) # 开启动画效果 self._chart.setAnimationOptions(QChart.SeriesAnimations) self._series = QPieSeries() self._series.setPieSize(0.8) self._chart.addSeries(self._series) self.setChart(self._chart) def refresh(self): # 提示widget self.toolTipWidget = GraphicsProxyWidget(self._chart) def mouseMoveEvent(self, event): super(pieChartView, self).mouseMoveEvent(event) pos = event.pos() x = pos.x() y = pos.y() # 得到在坐标系中的所有区域 self.min_x, self.max_x = self._chart.geometry().width( ) * 0.2, self._chart.geometry().width() * 0.8 self.min_y, self.max_y = self._chart.geometry().height( ) * 0.2, self._chart.geometry().height() * 0.9 serie = self._chart.series()[0] slices = [(slice, slice.value()) for slice in serie.slices()] if self.min_x <= x <= self.max_x and self.min_y <= y <= self.max_y: t_width = self.toolTipWidget.width() t_height = self.toolTipWidget.height() title = "数据组成" # 如果鼠标位置离右侧的距离小于tip宽度 x = pos.x() - t_width if self.width() - \ pos.x() - 20 < t_width else pos.x() # 如果鼠标位置离底部的高度小于tip高度 y = pos.y() - t_height if self.height() - \ pos.y() - 20 < t_height else pos.y() self.toolTipWidget.show(title, slices, QPoint(x, y)) else: self.toolTipWidget.hide()
class Chart(QChartView): def __init__(self, barCount: int): super().__init__() self.chart = QChart() self.setChart(self.chart) self.setRenderHint(QPainter.Antialiasing) self.chart.setAnimationOptions(QChart.SeriesAnimations) self.chart.setBackgroundVisible(True) self.chart.legend().setVisible(False) self.series = QBarSeries() self.chart.addSeries(self.series) self.barValues = QBarSet('') self.series.append(self.barValues) for i in range(barCount): self.barValues << 0. self.xAxis = QBarCategoryAxis() self.chart.addAxis(self.xAxis, Qt.AlignBottom) self.series.attachAxis(self.xAxis) self.xAxis.setTitleText('yPlus ranges') self.yAxis = QValueAxis() self.chart.addAxis(self.yAxis, Qt.AlignLeft) self.series.attachAxis(self.yAxis) self.yAxis.setTitleText('% of surface area') self.yAxis.setRange(0, 100) def setBarRanges(self, pois: List[float]): for i in range(len(pois)): if i == 0: tag = 'lt ' + str(pois[0]) elif i == len(pois) - 1: tag = 'gt ' + str(pois[-1]) else: tag = str(pois[i]) + ' - ' + str(pois[i + 1]) if not self.xAxis.count(): self.xAxis.append(tag) else: self.xAxis.replace(self.xAxis.at(i), tag) def setBarValues(self, values: List[float]): assert len(values) == self.barValues.count() for i in range(len(values)): if not self.barValues.count(): self.barValues.insert(i, 0.) else: self.barValues.replace(i, values[i])
def make_cake( self ): score_1 = self.players[ 0 ].score score_2 = self.players[ 1 ].score series = QPieSeries() free_score = 120 - score_1 - score_2 series.append( f"{free_score}", free_score ) series.append( f"{score_1}", score_1 ) series.append( f"{score_2}", score_2 ) series.setPieStartAngle( 3 * score_2 ) series.setPieEndAngle( 3 * score_2 + 360 ) slices = series.slices() for slice in slices: slice.setLabelVisible( True ) if slice.angleSpan() < 45: slice.setLabelPosition( QPieSlice.LabelPosition.LabelInsideNormal ) elif slice.angleSpan() < 90: slice.setLabelPosition( QPieSlice.LabelPosition.LabelInsideTangential ) else: slice.setLabelPosition( QPieSlice.LabelPosition.LabelInsideHorizontal ) slice.setLabelColor( QColor( "#00000" ) ) slice.setLabelFont( QFont( "Fira Sans", 60, weight=QFont.Weight.Black ) ) slice.setBorderWidth( 0 ) slices[ 0 ].setLabelPosition( QPieSlice.LabelPosition.LabelInsideHorizontal ) if score_1 < 10: slices[ 1 ].setLabelFont( QFont( "Fira Sans", score_1 * 6, weight=QFont.Weight.Black ) ) if score_2 < 10: slices[ 2 ].setLabelFont( QFont( "Fira Sans", score_2 * 6, weight=QFont.Weight.Black ) ) slices[ 0 ].setLabelColor( QColor( "#FFFFFF" ) ) slices[ 0 ].setColor( remaining_points_color ) slices[ 1 ].setColor( player_1.color ) slices[ 2 ].setColor( player_2.color ) chart = QChart() chart.legend().hide() chart.addSeries( series ) chart.createDefaultAxes() chart.setBackgroundVisible( False ) chart.setContentsMargins( -120, -120, -120, -120 ) chart.layout().setContentsMargins( 0, 0, 0, 0 ) chart_view = QChartView( chart ) chart_view.setRenderHint( QPainter.Antialiasing ) return chart_view
def create_histogram(self, series, max_val, animation=True): if animation: animation_type = QChart.AllAnimations else: animation_type = QChart.NoAnimation font_title = QFont() font_title.setBold(True) font_title.setPointSize(13) chart = QChart() chart.addSeries(series) chart.setTitle('Histogram of Bot Scores') chart.setTitleFont(font_title) chart.setBackgroundVisible(False) chart.setMargins(QMargins()) chart.setAnimationOptions(animation_type) scores = ('0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9') axisX = QBarCategoryAxis() axisX.setTitleText("Bot Score") axisX.append(scores) axisY = QValueAxis() axisY.setTitleText("Number Of Tweets") axisY.setRange(0, max_val) chart.addAxis(axisX, Qt.AlignBottom) chart.addAxis(axisY, Qt.AlignLeft) chart.legend().setVisible(False) chart.legend().setAlignment(Qt.AlignBottom) self.ui.histogram.setChart(chart) self.ui.histogram.setRenderHint(QPainter.Antialiasing) QApplication.processEvents()
class MonitorTab(object): def setupUi(self, Form): Form.setObjectName("Form") Form.resize(1550, 750) self.gridLayout_2 = QtWidgets.QGridLayout() self.gridLayout_2.setObjectName("gridLayout_2") self.gridLayout = QtWidgets.QGridLayout() self.gridLayout.setObjectName("gridLayout") self.chart4 = QChart() self.chart4.setMargins(QMargins(0, 0, 0, 0)) self.chart4.setBackgroundVisible(False) self.chart4.legend().setVisible(False) self.chartView4 = QChartView(self.chart4) self.gridLayout.addWidget(self.chartView4, 7, 0, 1, 1) self.chart3 = QChart() self.chart3.setMargins(QMargins(0, 0, 0, 0)) self.chart3.setBackgroundVisible(False) self.chart3.legend().setVisible(False) self.chartView3 = QChartView(self.chart3) self.gridLayout.addWidget(self.chartView3, 5, 0, 1, 1) self.chart2 = QChart() self.chart2.setMargins(QMargins(0, 0, 0, 0)) self.chart2.setBackgroundVisible(False) self.chart2.legend().setVisible(False) self.chartView2 = QChartView(self.chart2) self.gridLayout.addWidget(self.chartView2, 3, 0, 1, 1) self.chart1 = QChart() self.chart1.setMargins(QMargins(0, 0, 0, 0)) self.chart1.setBackgroundVisible(False) self.chartView = QChartView(self.chart1) self.chart1.legend().setVisible(False) self.gridLayout.addWidget(self.chartView, 1, 0, 1, 1) self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1) self.retranslateUi(Form) QtCore.QMetaObject.connectSlotsByName(Form) def retranslateUi(self, Form): _translate = QtCore.QCoreApplication.translate Form.setWindowTitle(_translate("Form", "MyForm"))
def create_piechart(self): series = QLineSeries() weights = SQLStatements.getallWeightChanges(self.userID) print(weights) weights = str(weights) weights = weights.replace("(", "") weights = weights.replace(")", "") weights = weights.replace(",", "") weights = weights.replace("[", "") weights = weights.replace("]", "") weightsTable = weights.split() print(weightsTable) count = 0 for x in weightsTable: x = int(float(x)) print(x) series.append(count, x) count = count + 2 chart = QChart() chart.addSeries(series) chart.setAnimationOptions(QChart.SeriesAnimations) chart.setTitle("Weight Change over time") chart.setTheme(QChart.ChartThemeBlueCerulean) chart.setBackgroundVisible(False) #Title Font size font = QFont("Sans Serif", ) font.setPixelSize(18) chart.setTitleFont(font) # X Axis Settings axisX = QValueAxis() axisX.setTitleText("Time") # Y Axis Settings axisY = QValueAxis() axisY.setTitleText("Weight (KG)") # Customize axis label font Lfont = QFont("Sans Serif") Lfont.setPixelSize(16) axisX.setLabelsFont(Lfont) axisY.setLabelsFont(Lfont) #add Axis chart.addAxis(axisX, Qt.AlignBottom) series.attachAxis(axisX) chart.addAxis(axisY, Qt.AlignLeft) series.attachAxis(axisY) chartview = QChartView(chart) chartview.setRenderHint(QPainter.Antialiasing) return chartview
class barChartView(QChartView): def __init__(self, xAxis=[], *args, **kwargs): super(barChartView, self).__init__(*args, **kwargs) self.initChart(xAxis) # line 宽度需要调整 self.lineItem = QGraphicsLineItem(self._chart) pen = QPen(Qt.gray) self.lineItem.setPen(pen) self.lineItem.setZValue(998) self.lineItem.hide() self.cal() # 一些固定计算,减少mouseMoveEvent中的计算量 def cal(self): # 提示widget self.toolTipWidget = GraphicsProxyWidget(self._chart) # 获取x和y轴的最小最大值 axisX, axisY = self._chart.axisX(), self._chart.axisY() self.category_len = len(axisX.categories()) self.min_x, self.max_x = -0.5, self.category_len - 0.5 self.min_y, self.max_y = axisY.min(), axisY.max() # 坐标系中左上角顶点 self.point_top = self._chart.mapToPosition( QPointF(self.min_x, self.max_y)) def setCat(self, data): self.categories = data #初始化 def initChart(self, xAxis): self._chart = QChart() # 调整边距 self._chart.layout().setContentsMargins(0, 0, 0, 0) # 外界 self._chart.setMargins(QMargins(3, 0, 3, 0)) # 内界 self._chart.setBackgroundRoundness(0) self._chart.setBackgroundVisible(False) # 设置主题 self._chart.setTheme(QChart.ChartThemeBlueIcy) # 抗锯齿 self.setRenderHint(QPainter.Antialiasing) # 开启动画效果 self._chart.setAnimationOptions(QChart.SeriesAnimations) self.categories = xAxis self._series = QBarSeries(self._chart) self._chart.addSeries(self._series) self._chart.createDefaultAxes() # 创建默认的轴 self._axis_x = QBarCategoryAxis(self._chart) self._axis_x.append(self.categories) self._axis_y = QValueAxis(self._chart) self._axis_y.setTitleText("任务数") self._axis_y.setRange(0, 10) self._chart.setAxisX(self._axis_x, self._series) self._chart.setAxisY(self._axis_y, self._series) # chart的图例 legend = self._chart.legend() legend.setVisible(True) self.setChart(self._chart) def mouseMoveEvent(self, event): super(barChartView, self).mouseMoveEvent(event) pos = event.pos() # 把鼠标位置所在点转换为对应的xy值 x = self._chart.mapToValue(pos).x() y = self._chart.mapToValue(pos).y() index = round(x) # 得到在坐标系中的所有bar的类型和点 serie = self._chart.series()[0] bars = [ (bar, bar.at(index)) for bar in serie.barSets() if self.min_x <= x <= self.max_x and self.min_y <= y <= self.max_y ] # print(bars) if bars: right_top = self._chart.mapToPosition( QPointF(self.max_x, self.max_y)) # 等分距离比例 step_x = round( (right_top.x() - self.point_top.x()) / self.category_len) posx = self._chart.mapToPosition(QPointF(x, self.min_y)) self.lineItem.setLine(posx.x(), self.point_top.y(), posx.x(), posx.y()) self.lineItem.show() try: title = self.categories[index] except: title = "" t_width = self.toolTipWidget.width() t_height = self.toolTipWidget.height() # 如果鼠标位置离右侧的距离小于tip宽度 x = pos.x() - t_width if self.width() - \ pos.x() - 20 < t_width else pos.x() # 如果鼠标位置离底部的高度小于tip高度 y = pos.y() - t_height if self.height() - \ pos.y() - 20 < t_height else pos.y() self.toolTipWidget.show(title, bars, QPoint(x, y)) else: self.toolTipWidget.hide() self.lineItem.hide()
class DistributionPieChart(QChartView): """ Pie chart that shows the distribution of capital according to several criteria """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Chart self.chart = QChart() self.chart.setTheme(QChart.ChartThemeDark) self.chart.legend().hide() self.chart.createDefaultAxes() self.chart.setAnimationOptions(QChart.SeriesAnimations) self.chart.setBackgroundVisible(False) self.chart.setTitle(" ") self.chart.setTitleBrush(QBrush(QColor('white'))) self.setChart(self.chart) self.setRenderHint(QPainter.Antialiasing) self.setStyleSheet("border: 0px; background-color: rgba(0,0,0,0)") self.setupSeries() # Initialize to all mode def setupSeries(self, mode="all"): """ Chart gets updated displaying the new data. Modes: - all : distribution between all accounts - accs : distribution between portfolio accounts - cryptoaccs : distribution between crypto accounts - strategies : distribution between strategies """ # Series self.chart.removeAllSeries() # Remove any previous series self.series = QPieSeries() # Get data if mode == "all": data = balances.get_all_accounts( ) + cbalances.get_all_accounts_with_amount_fiat() elif mode == "accounts": data = balances.get_all_accounts() elif mode == "crypto": data = cbalances.get_all_accounts_with_amount_fiat() elif mode == "currency": data = [(confighandler.get_fiat_currency().upper(), balances.get_total_balance_all_accounts( )), ("BTC", cbalances.get_total_balance_all_accounts_fiat())] data.sort(key=lambda x: x[1]) # Sort # Set Chart Title self.total = sum([i[1] for i in data]) self.setDefaultTitle() # Add to series for d in data: self.series.append(d[0], d[1]) # Hide little slices' labels self.series.setLabelsVisible(True) for slc in self.series.slices(): if slc.angleSpan() < 5: slc.setLabelVisible(False) slc.setLabelArmLengthFactor(0.05) self.chart.addSeries(self.series) # Signals and functionality self.series.hovered.connect(self.selectSlice) def selectSlice(self, _slice, state): """ Highlight selected slice """ font = ChartTitleFont() if state: font.setPointSize(20) _slice.setLabelVisible(True) self.chart.setTitle( f"{int(_slice.value())} {confighandler.get_fiat_currency().upper()} {round(_slice.percentage()*100,1)}%") else: font.setBold(False) if _slice.angleSpan() < 5: _slice.setLabelVisible(False) _slice.setExploded(False) self.setDefaultTitle() _slice.setLabelFont(font) def setDefaultTitle(self): """ Sets title as total balance from all pie slices """ self.chart.setTitle( f"{int(self.total)} {confighandler.get_fiat_currency().upper()}") font = ChartTitleFont(fontsize=20) self.chart.setTitleFont(font)
class Statistics(QWidget): """A statistics widget that displays information about studied time, shows grown plants, etc...""" def __init__(self, history, *args, **kwargs): super().__init__(*args, **kwargs) self.history = history chart = self.generate_chart() self.SPACING = 10 self.MIN_WIDTH = 400 self.MIN_HEIGHT = 200 chart.setMinimumWidth(self.MIN_WIDTH) chart.setMinimumHeight(self.MIN_HEIGHT) image_layout = QVBoxLayout() self.plant_study = None # the study record the plant is a part of self.plant: Optional[Plant] = None # the plant being displayed self.plant_date_label = QLabel(self) self.plant_date_label.setAlignment(Qt.AlignLeft) self.plant_duration_label = QLabel(self) self.plant_duration_label.setAlignment(Qt.AlignRight) label_layout = QHBoxLayout() label_layout.addWidget(self.plant_date_label) label_layout.addWidget(self.plant_duration_label) self.canvas = Canvas(self) self.canvas.setMinimumWidth(self.MIN_HEIGHT) self.canvas.setMinimumHeight(self.MIN_HEIGHT) stacked_layout = QVBoxLayout() stacked_layout.addLayout(label_layout) stacked_layout.addWidget(self.canvas) image_control = QHBoxLayout() text_color = self.palette().text().color() self.age_slider = QSlider(Qt.Horizontal, minimum=0, maximum=1000, value=1000, valueChanged=self.slider_value_changed) self.left_button = QPushButton(self, clicked=self.left, icon=qtawesome.icon('fa5s.angle-left', color=text_color)) self.right_button = QPushButton(self, clicked=self.right, icon=qtawesome.icon('fa5s.angle-right', color=text_color)) self.save_button = QPushButton(self, clicked=self.save, icon=qtawesome.icon('fa5s.download', color=text_color)) image_control.addWidget(self.left_button) image_control.addWidget(self.right_button) image_control.addSpacing(self.SPACING) image_control.addWidget(self.age_slider) image_control.addSpacing(self.SPACING) image_control.addWidget(self.save_button) image_layout.addLayout(stacked_layout) image_layout.addLayout(image_control) image_layout.setContentsMargins(self.SPACING, self.SPACING, self.SPACING, self.SPACING) separator = QFrame() separator.setStyleSheet(f"background-color: {self.palette().text().color().name()}") separator.setFixedWidth(1) main_layout = QGridLayout() main_layout.setHorizontalSpacing(self.SPACING * 2) main_layout.setColumnStretch(0, 1) main_layout.setColumnStretch(2, 0) main_layout.addWidget(chart, 0, 0) main_layout.addWidget(separator, 0, 1) main_layout.addLayout(image_layout, 0, 2) self.setLayout(main_layout) self.move() # go to the most recent plant self.refresh() def generate_chart(self): """Generate the bar graph for the widget.""" self.tags = [QBarSet(tag) for tag in ["Study"]] series = QStackedBarSeries() for set in self.tags: series.append(set) self.chart = QChart() self.chart.addSeries(series) self.chart.setTitle("Total time studied (minutes per day)") days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] axis = QBarCategoryAxis() axis.append(days) self.chart.createDefaultAxes() self.chart.setAxisX(axis, series) self.chart.legend().setAlignment(Qt.AlignBottom) self.chart.legend().setVisible(False) self.chart.setTheme(QChart.ChartThemeQt) self.chart.setBackgroundVisible(False) self.chart.setBackgroundRoundness(0) self.chart.setMargins(QMargins(0, 0, 0, 0)) self.chart.setTitleBrush(QBrush(self.palette().text().color())) yAxis = self.chart.axes(Qt.Vertical)[0] yAxis.setGridLineVisible(False) yAxis.setLabelFormat("%d") yAxis.setLinePenColor(self.palette().text().color()) yAxis.setLabelsColor(self.palette().text().color()) xAxis = self.chart.axes(Qt.Horizontal)[0] xAxis.setGridLineVisible(False) xAxis.setLinePenColor(self.palette().text().color()) xAxis.setLabelsColor(self.palette().text().color()) chartView = QChartView(self.chart) chartView.setRenderHint(QPainter.Antialiasing) return chartView def slider_value_changed(self): """Called when the slider value has changed. Sets the age of the plant and updates it.""" if self.plant is not None: # makes it a linear function from 0 to whatever the duration was, so the plant appears to grow normally self.plant.set_age( self.plant.inverse_age_coefficient_function(self.age_slider.value() / self.age_slider.maximum() * self.plant.age_coefficient_function( self.plant_study["duration"]))) self.canvas.update() def refresh(self): """Refresh the labels.""" # clear tag values for tag in self.tags: tag.remove(0, tag.count()) study_minutes = [0] * 7 for study in self.history.get_studies(): # TODO: don't just crash study_minutes[study["date"].weekday()] += study["duration"] for minutes in study_minutes: self.tags[0] << minutes # manually set the range of the y axis, because it doesn't for some reason yAxis = self.chart.axes(Qt.Vertical)[0] yAxis.setRange(0, max(study_minutes)) def left(self): """Move to the left (older) plant.""" self.move(-1) def right(self): """Move to the right (newer) plant.""" self.move(1) def move(self, delta: int = 0): """Move to the left/right plant by delta. If no plant is currently being displayed or delta is 0, pick the latest one.""" studies = self.history.get_studies() # if there are no plants to display, don't do anything if len(studies) == 0: return # if no plant is being displayed or 0 is provided, pick the last one if self.plant is None or delta == 0: index = -1 # if one is, find it and move by delta else: current_index = self.history.get_studies().index(self.plant_study) index = max(min(current_index + delta, len(studies) - 1), 0) # TODO: check for correct formatting, don't just crash if it's wrong self.plant = pickle.loads(studies[index]["plant"]) self.plant_study = studies[index] # TODO: check for correct formatting, don't just crash if it's wrong self.plant_date_label.setText(self.plant_study["date"].strftime("%-d/%-m/%Y")) self.plant_duration_label.setText(f"{int(self.plant_study['duration'])} minutes") self.canvas.set_drawable(self.plant) self.slider_value_changed() # it didn't, but the code should act as if it did (update plant) def save(self): """Save the current state of the plant to a file.""" if self.plant is not None: name, _ = QFileDialog.getSaveFileName(self, 'Save File', "", "SVG files (*.svg)") if name == "": return if not name.endswith(".svg"): name += ".svg" self.plant.save(name, 1000, 1000)
def create_piechart(self): Date = date.today() breakfastData = SQLStatements.getTotalBreakfastCalories( self.userID, Date) breakfastData = str(breakfastData) breakfastData = (breakfastData.replace("[", "")) breakfastData = (breakfastData.replace("]", "")) breakfastData = (breakfastData.replace("(", "")) breakfastData = (breakfastData.replace(")", "")) breakfastData = (breakfastData.replace(",", "")) breakfastData = int(breakfastData) lunchData = SQLStatements.getTotalLunchCalories(self.userID, Date) lunchData = str(lunchData) lunchData = (lunchData.replace("[", "")) lunchData = (lunchData.replace("]", "")) lunchData = (lunchData.replace("(", "")) lunchData = (lunchData.replace(")", "")) lunchData = (lunchData.replace(",", "")) lunchData = int(lunchData) dinnerData = SQLStatements.getTotalDinnerCalories(self.userID, Date) dinnerData = str(dinnerData) dinnerData = (dinnerData.replace("[", "")) dinnerData = (dinnerData.replace("]", "")) dinnerData = (dinnerData.replace("(", "")) dinnerData = (dinnerData.replace(")", "")) dinnerData = (dinnerData.replace(",", "")) dinnerData = int(dinnerData) snackData = SQLStatements.getTotalSnacksCalories(self.userID, Date) snackData = str(snackData) snackData = (snackData.replace("[", "")) snackData = (snackData.replace("]", "")) snackData = (snackData.replace("(", "")) snackData = (snackData.replace(")", "")) snackData = (snackData.replace(",", "")) snackData = int(snackData) series = QPieSeries() series.append("Breakfast calories", breakfastData) series.append("Lunch calories", lunchData) series.append("Dinner calories", dinnerData) series.append("Snack calories", snackData) labelFont = QFont("Sans Serif", ) labelFont.setPixelSize(16) slice = QPieSlice() slice.setLabelFont(labelFont) slice = series.slices()[0] slice.setExploded(True) slice.setLabelVisible(True) slice.setPen(QPen(Qt.green, 2)) slice.setBrush(Qt.green) slice = QPieSlice() slice.setLabelFont(labelFont) slice = series.slices()[1] slice.setExploded(True) slice.setLabelVisible(True) slice.setPen(QPen(Qt.white, 2)) slice.setBrush(Qt.white) slice = QPieSlice() slice.setLabelFont(labelFont) slice = series.slices()[2] slice.setExploded(True) slice.setLabelVisible(True) slice.setPen(QPen(Qt.yellow, 2)) slice.setBrush(Qt.yellow) slice = QPieSlice() slice.setLabelFont(labelFont) slice = series.slices()[3] slice.setExploded(True) slice.setLabelVisible(True) slice.setPen(QPen(Qt.yellow, 2)) slice.setBrush(Qt.yellow) chart = QChart() chart.legend().hide() chart.addSeries(series) chart.createDefaultAxes() chart.setAnimationOptions(QChart.SeriesAnimations) chart.setTitle("Daily Calories") chart.setTheme(QChart.ChartThemeBlueCerulean) chart.setBackgroundVisible(False) # Title Font size font = QFont("Sans Serif", ) font.setPixelSize(18) chart.setTitleFont(font) chart.legend().setVisible(True) chart.legend().setAlignment(Qt.AlignBottom) chartview = QChartView(chart) chartview.setRenderHint(QPainter.Antialiasing) return chartview
class ChartView(QChartView): def __init__(self, file, parent=None): super(ChartView, self).__init__(parent) self._chart = QChart() self._chart.setAcceptHoverEvents(True) self.setChart(self._chart) self.initUi(file) def initUi(self, file): if isinstance(file, dict): return self.__analysis(file) if isinstance(file, str): if not os.path.isfile(file): return self.__analysis(json.loads(file)) with open(file, "rb") as fp: data = fp.read() encoding = chardet.detect(data) or {} data = data.decode(encoding.get("encoding") or "utf-8") self.__analysis(json.loads(data)) # def onSeriesHoverd(self, point, state): # print(point, state) def mouseMoveEvent(self, event): super(ChartView, self).mouseMoveEvent(event) # 获取x和y轴的最小最大值 axisX, axisY = self._chart.axisX(), self._chart.axisY() min_x, max_x = axisX.min(), axisX.max() min_y, max_y = axisY.min(), axisY.max() # 把鼠标位置所在点转换为对应的xy值 x = self._chart.mapToValue(event.pos()).x() y = self._chart.mapToValue(event.pos()).y() index = round(x) # 四舍五入 print(x, y, index) # 得到在坐标系中的所有series的类型和点 points = [(s.type(), s.at(index)) for s in self._chart.series() if min_x <= x <= max_x and min_y <= y <= max_y] print(points) def __getColor(self, color=None, default=Qt.white): ''' :param color: int|str|[r,g,b]|[r,g,b,a] ''' if not color: return QColor(default) if isinstance(color, QBrush): return color # 比如[r,g,b]或[r,g,b,a] if isinstance(color, list) and 3 <= len(color) <= 4: return QColor(*color) else: return QColor(color) def __getPen(self, pen=None, default=QPen(Qt.white, 1, Qt.SolidLine, Qt.SquareCap, Qt.BevelJoin)): ''' :param pen: pen json ''' if not pen or not isinstance(pen, dict): return default return QPen(self.__getColor(pen.get("color", None) or default.color()), pen.get("width", 1) or 1, pen.get("style", 0) or 0, pen.get("capStyle", 16) or 16, pen.get("joinStyle", 64) or 64) def __getAlignment(self, alignment): ''' :param alignment: left|top|right|bottom ''' try: return getattr(Qt, "Align" + alignment.capitalize()) except: return Qt.AlignTop # if alignment == "left": # return Qt.AlignLeft # if alignment == "right": # return Qt.AlignRight # if alignment == "bottom": # return Qt.AlignBottom # return Qt.AlignTop def __setTitle(self, title=None): ''' :param title: title json ''' if not title or not isinstance(title, dict): return # 设置标题 self._chart.setTitle(title.get("text", "") or "") # 设置标题颜色 self._chart.setTitleBrush( self.__getColor( title.get("color", self._chart.titleBrush()) or self._chart.titleBrush())) # 设置标题字体 font = QFont(title.get("font", "") or self._chart.titleFont()) pointSize = title.get("pointSize", -1) or -1 if pointSize > 0: font.setPointSize(pointSize) font.setWeight(title.get("weight", -1) or -1) font.setItalic(title.get("italic", False) or False) self._chart.setTitleFont(font) def __setAnimation(self, animation=None): ''' :param value: animation json ''' if not animation or not isinstance(animation, dict): return # 动画持续时间 self._chart.setAnimationDuration( animation.get("duration", 1000) or 1000) # 设置动画曲线 self._chart.setAnimationEasingCurve( EasingCurve.get(animation.get("curve", 10) or 10, None) or QEasingCurve.OutQuart) # 设置开启何种动画 self._chart.setAnimationOptions( AnimationOptions.get(animation.get("options", 0) or 0, None) or QChart.NoAnimation) def __setBackground(self, background=None): ''' :param background:background json ''' if not background or not isinstance(background, dict): return # 设置是否背景可用 self._chart.setBackgroundVisible( background.get("visible", True) or True) # 设置背景矩形的圆角 self._chart.setBackgroundRoundness(background.get("radius", 0) or 0) # 设置下拉阴影 self._chart.setDropShadowEnabled( background.get("dropShadow", True) or True) # 设置pen self._chart.setBackgroundPen( self.__getPen(background.get("pen", None), self._chart.backgroundPen())) # 设置背景 image = background.get("image", None) color = background.get("color", None) if image: self._chart.setBackgroundBrush(QBrush(QPixmap(image))) elif color: self._chart.setBackgroundBrush( self.__getColor(color, self._chart.backgroundBrush())) def __setMargins(self, margins=None): ''' :param margins: margins json ''' if not margins or not isinstance(margins, dict): return left = margins.get("left", 20) or 20 top = margins.get("top", 20) or 20 right = margins.get("right", 20) or 20 bottom = margins.get("bottom", 20) or 20 self._chart.setMargins(QMargins(left, top, right, bottom)) def __setLegend(self, legend=None): ''' :param legend: legend json ''' if not legend or not isinstance(legend, dict): return _legend = self._chart.legend() _legend.setAlignment(self.__getAlignment(legend.get("alignment", None))) _legend.setShowToolTips(legend.get("showToolTips", True) or True) def __getSerie(self, serie=None): if not serie or not isinstance(serie, dict): return None types = serie.get("type", "") or "" data = serie.get("data", []) or [] if not data or not isinstance(data, list): return None if types == "line": _series = QLineSeries(self._chart) else: return None # 设置series名字 _series.setName(serie.get("name", "") or "") # 添加数据到series中 for index, value in enumerate(data): # 保证vlaue必须是数字 _series.append(index, value if type(value) in (int, float) else 0) return _series def __setSeries(self, series=None): if not series or not isinstance(series, list): return for serie in series: _serie = self.__getSerie(serie) if _serie: # _serie.hovered.connect(self.onSeriesHoverd) self._chart.addSeries(_serie) # 创建默认的xy轴 self._chart.createDefaultAxes() def __setAxisX(self, axisx=None): if not axisx or not isinstance(axisx, dict): return series = self._chart.series() if not series: return types = axisx.get("type", None) data = axisx.get("data", []) or [] if not data or not isinstance(data, list): return None minx = self._chart.axisX().min() maxx = self._chart.axisX().max() if types == "category": xaxis = QCategoryAxis( self._chart, labelsPosition=QCategoryAxis.AxisLabelsPositionOnValue) # 隐藏网格 xaxis.setGridLineVisible(False) # 刻度条数 tickc_d = len(data) tickc = tickc_d if tickc_d > 1 else self._chart.axisX().tickCount() xaxis.setTickCount(tickc) # 强制x轴刻度与新刻度条数一致 self._chart.axisX().setTickCount(tickc) step = (maxx - minx) / (tickc - 1) for i in range(min(tickc_d, tickc)): xaxis.append(data[i], minx + i * step) self._chart.setAxisX(xaxis, series[-1]) def __analysis(self, datas): ''' analysis json data :param datas: json data ''' # 标题 self.__setTitle(datas.get("title", None)) # 抗锯齿 if (datas.get("antialiasing", False) or False): self.setRenderHint(QPainter.Antialiasing) # 主题 self._chart.setTheme(datas.get("theme", 0) or 0) # 动画 self.__setAnimation(datas.get("animation", None)) # 背景设置 self.__setBackground(datas.get("background", None)) # 边距设置 self.__setMargins(datas.get("margins", None)) # 设置图例 self.__setLegend(datas.get("legend", None)) # 设置series self.__setSeries(datas.get("series", None)) # 自定义的x轴 self.__setAxisX(datas.get("axisx", None))
class MainUI(QtWidgets.QMainWindow): def __init__(self, parent=None): super(MainUI, self).__init__(parent) self.init_ui() self.left_add_init() self.right_down_add_init() def init_ui(self): self.resize(900, 600) self.setWindowOpacity(0.9) self.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5()) self.main_widget = QtWidgets.QWidget() self.main_layout = QtWidgets.QGridLayout() self.main_widget.setLayout(self.main_layout) self.left_frame = QtWidgets.QFrame() self.left_frame.setObjectName("left_frame") self.left_frame.setFrameShape(QFrame.StyledPanel) self.left_layout = QtWidgets.QGridLayout() self.left_frame.setLayout(self.left_layout) self.right_up_frame = QtWidgets.QFrame() self.right_up_frame.setObjectName("right_up_frame") self.right_up_frame.setFrameShape(QFrame.StyledPanel) self.right_up_layout = QStackedLayout() self.right_up_frame.setLayout(self.right_up_layout) self.right_down_frame = QtWidgets.QFrame() self.right_down_frame.setObjectName("right_down_frame") self.right_down_frame.setFrameShape(QFrame.StyledPanel) self.right_down_layout = QtWidgets.QGridLayout() self.right_down_frame.setLayout(self.right_down_layout) ''' self.right_down_frame.setLayout(self.right_down_layout) self.main_layout.addWidget(self.left_frame, 0, 0, 12, 2) self.main_layout.addWidget(self.right_up_frame, 0, 2, 7, 10) self.main_layout.addWidget(self.right_down_frame, 7, 2, 5, 10) ''' self.splitter1 = QSplitter(Qt.Vertical) self.splitter1.addWidget(self.right_up_frame) self.splitter1.addWidget(self.right_down_frame) self.splitter1.setSizes([400, 300]) self.splitter2 = QSplitter(Qt.Horizontal) self.splitter2.addWidget(self.left_frame) self.splitter2.addWidget(self.splitter1) self.splitter2.setSizes([200, 800]) self.main_layout.addWidget(self.splitter2) self.setCentralWidget(self.main_widget) def left_add_init(self): self.left_button_1 = QtWidgets.QPushButton("个人信息") self.left_button_1.setObjectName('left_button_1') self.left_layout.addWidget(self.left_button_1, 0, 0, 1, 1) self.left_button_2 = QtWidgets.QPushButton("退出") self.left_button_2.setObjectName('left_button_2') self.left_layout.addWidget(self.left_button_2, 1, 0, 2, 1) def right_down_add_init(self): self.chart = QChart() self.chart.setTitle("Line Chart 1") series = QLineSeries(self.chart) series.append(0, 6) series.append(2, 4) self.chart.addSeries(series) self.chart.setBackgroundVisible(False) self.chart.createDefaultAxes() # 创建默认轴 self.view = QChartView(self.chart) self.view.setRenderHint(QPainter.Antialiasing) # 抗锯齿 self.right_down_layout.addWidget(self.view, 0, 0, 1, 1) series.append(1, 4) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.m_flag = True self.m_Position = event.globalPos() - self.pos() # 获取鼠标相对窗口的位置 event.accept() self.setCursor(QCursor(Qt.OpenHandCursor)) # 更改鼠标图标 def mouseMoveEvent(self, QMouseEvent): if Qt.LeftButton and self.m_flag: self.move(QMouseEvent.globalPos() - self.m_Position) # 更改窗口位置 QMouseEvent.accept() def mouseReleaseEvent(self, QMouseEvent): self.m_flag = False self.setCursor(QCursor(Qt.ArrowCursor))