class Chart(QChart): def __init__(self, parent=None): super(Chart, self).__init__(parent=parent) title_font = QFont('Roboto', pointSize=8) labels_font = QFont('Roboto', pointSize=2) self.setTitleFont(title_font) self.axesX = QCategoryAxis() self.axesY = QCategoryAxis() self.axesX.setLabelsFont(labels_font) self.axesY.setLabelsFont(labels_font) self.setAxisX(self.axesX) self.setAxisY(self.axesY) def gestureEvent(self, event): if event.gesture(Qt.PanGesture): pass def sceneEvent(self, event): if event.type() == QEvent.GraphicsSceneWheel: if event.delta() > 0: self.zoom(1.05) if event.delta() < 0: self.zoom(0.95) return super(Chart, self).sceneEvent(event) def wheelEvent(self, event): return super(Chart, self).wheelEvent(event)
def lines_stacked(name, table_df, x_bottom_cols, y_left_cols, y_right_cols, legend_labels, tick_count): """ 折线堆叠图 :param name: 图表名称 :param table_df: 用于画图的pandas DataFrame对象 :param x_bottom_cols: 下轴列索引列表 :param y_left_cols: 左轴列索引列表 :param y_right_cols: 右轴列索引列表 :param legend_labels: 图例名称标签列表 :param tick_count: 横轴刻度标签数 :return: QChart实例 """ """ 过滤轴 """ for y_left_col in y_left_cols: if is_datetime64_any_dtype(table_df[y_left_col]): # 如果是时间轴 y_left_cols.remove(y_left_col) for y_right_col in y_right_cols: if is_datetime64_any_dtype(table_df[y_right_col]): # 如果是时间轴 y_right_cols.remove(y_right_col) # 将x轴转为字符串 x_bottom = x_bottom_cols[0] # x轴列 if is_datetime64_any_dtype(table_df[x_bottom]): # 如果x轴是时间轴 table_df[x_bottom] = table_df[x_bottom].apply( lambda x: x.strftime('%Y-%m-%d')) else: # x轴非时间轴 table_df[x_bottom] = table_df[x_bottom].apply(lambda x: str(x)) font = QFont() # 轴文字风格 font.setPointSize(7) # 轴标签文字大小 chart = QChart() # 图表实例 chart.layout().setContentsMargins(0, 0, 0, 0) # chart的外边距 chart.setMargins(QMargins(15, 5, 15, 0)) # chart内边距 chart.setTitle(name) # chart名称 """ x轴 """ axis_x_bottom = QCategoryAxis( chart, labelsPosition=QCategoryAxis.AxisLabelsPositionOnValue) axis_x_bottom.setLabelsAngle(-90) # 逆时针旋转90度 axis_x_bottom.setLabelsFont(font) # 设置字体样式 axis_x_bottom.setGridLineVisible(False) # 竖向连接线不可见 chart.addAxis(axis_x_bottom, Qt.AlignBottom) # 加入坐标x轴 has_x_labels = False # 收集x轴刻度的开关 chart.x_labels = list() # 绑定chart一个x轴的刻度列表 """ 左Y轴 """ axis_y_left = QValueAxis() axis_y_left.setLabelsFont(font) axis_y_left.setLabelFormat('%i') chart.addAxis(axis_y_left, Qt.AlignLeft) # 图表加入左轴 """ 右Y轴 """ axis_y_right = QValueAxis() axis_y_right.setLabelsFont(font) axis_y_right.setLabelFormat('%.2f') chart.addAxis(axis_y_right, Qt.AlignRight) # 记录各轴的最值 x_bottom_min, x_bottom_max = 0, table_df.shape[0] y_left_min, y_left_max = 0, 0 y_right_min, y_right_max = 0, 0 """ 根据左轴画折线 """ for y_left_col in y_left_cols: # 根据左轴画折线 # 计算做轴的最值用于设置范围 table_df[y_left_col] = table_df[y_left_col].apply( covert_float) # y轴列转为浮点数值 # 获取最值 y_min, y_max = table_df[y_left_col].min(), table_df[y_left_col].max() if y_min < y_left_min: y_left_min = y_min if y_max > y_left_max: y_left_max = y_max # 取得图线的源数据作折线图 left_line_data = table_df.iloc[:, [x_bottom, y_left_col]] series = QLineSeries() series.setName(legend_labels[y_left_col]) for position_index, point_item in enumerate( left_line_data.values.tolist()): series.append(position_index, point_item[1]) # 取出源数据后一条线就2列数据 # 收集坐标标签 if not has_x_labels: chart.x_labels.append(point_item[0]) chart.addSeries(series) # 折线入图 series.attachAxis(axis_x_bottom) series.attachAxis(axis_y_left) # 左轴范围 axis_y_left.setRange(y_left_min, y_left_max) """ 根据右轴画折线 """ for y_right_col in y_right_cols: # 根据右轴画折线 # 计算做轴的最值用于设置范围 table_df[y_right_col] = table_df[y_right_col].apply( covert_float) # y轴列转为浮点数值 # 获取最值 y_min, y_max = table_df[y_right_col].min(), table_df[y_right_col].max() if y_min < y_right_min: y_right_min = y_min if y_max > y_right_max: y_right_max = y_max # 取得图线的源数据作折线图 left_line_data = table_df.iloc[:, [x_bottom, y_right_col]] series = QLineSeries() series.setName(legend_labels[y_right_col]) for position_index, point_item in enumerate( left_line_data.values.tolist()): series.append(position_index, point_item[1]) # 取出源数据后一条线就2列数据 chart.addSeries(series) series.attachAxis(axis_x_bottom) series.attachAxis(axis_y_right) # 右轴范围 axis_y_right.setRange(y_right_min, y_right_max) # 设置下轴刻度标签 # print('x轴最大值', x_bottom_max) x_bottom_interval = int(x_bottom_max / (tick_count - 1)) if x_bottom_interval == 0: for i in range(0, x_bottom_max): axis_x_bottom.append(chart.x_labels[i], i) else: for i in range(0, x_bottom_max, x_bottom_interval): axis_x_bottom.append(chart.x_labels[i], i) chart.legend().setAlignment(Qt.AlignBottom) return chart
def __init__(self, parent=None): super(Widget, self).__init__(parent) self.setWindowTitle('Financieële grafieken externe werken') self.setWindowIcon(QIcon('./images/logos/logo.jpg')) self.setWindowFlags(self.windowFlags() | Qt.WindowSystemMenuHint | Qt.WindowMinMaxButtonsHint) grid = QGridLayout() grid.setSpacing(20) metadata = MetaData() resultaten = Table('resultaten', metadata, Column('resID', Integer(), primary_key=True), Column('statusweek', String), Column('btotaal', Float), Column('wtotaal', Float), Column('betaald_bedrag', Float), Column('meerminderwerk', Float), Column('onderhandenwerk', Float), Column('aanneemsom', Float), Column('blonen', Float), Column('wlonen', Float), Column('bmaterialen', Float), Column('wmaterialen', Float), Column('bmaterieel', Float), Column('wmaterieel', Float), Column('bprojectkosten', Float), Column('wprojectkosten', Float), Column('binhuur', Float), Column('winhuur', Float), Column('bdiensten', Float), Column('wdiensten', Float), Column('bruto_winst', Float), Column('boekweek', String)) params = Table('params', metadata, Column('paramID', Integer(), primary_key=True), Column('tarief', String)) engine = create_engine( 'postgresql+psycopg2://postgres@localhost/bisystem') con = engine.connect() selpar1 = select([params]).where(params.c.paramID == 97) rppar1 = con.execute(selpar1).first() bo_incr = rppar1[1] / 52 #begrote omzet per week selpar2 = select([params]).where(params.c.paramID == 98) rppar2 = con.execute(selpar2).first() bw_incr = rppar2[1] / 52 #begrote winst per week jaar = jrwk[0:4] engine = create_engine( 'postgresql+psycopg2://postgres@localhost/bisystem') con = engine.connect() selres = select([resultaten]).where(and_(resultaten.c.boekweek == jrwk,\ resultaten.c.statusweek.like(jaar+'%'))).order_by(resultaten.c.statusweek) rpres = con.execute(selres) if keuze == '1': s1 = 2 s2 = 3 t1 = 'Kosten totaal begroot' t2 = 'Kosten totaal werkelijk' t3 = 'Kosten totaal ' c1 = Qt.red c2 = Qt.blue ysch = 160000000 elif keuze == '2': s1 = 8 s2 = 9 t1 = 'Lonen begroot' t2 = 'Lonen werkelijk' t3 = 'Lonen ' c1 = Qt.green c2 = Qt.darkBlue ysch = 100000000 elif keuze == '3': s1 = 10 s2 = 11 t1 = 'Materialen begroot' t2 = 'Materialen werkelijk' t3 = 'Materialen' c1 = Qt.cyan c2 = Qt.magenta ysch = 60000000 elif keuze == '4': s1 = 12 s2 = 13 t1 = 'Materiëel begroot' t2 = 'Materiëel werkelijk' t3 = 'Materiëel ' c1 = Qt.darkYellow c2 = Qt.darkGreen ysch = 20000000 elif keuze == '5': s1 = 16 s2 = 17 t1 = 'Inhuur begroot' t2 = 'Inhuur werkelijk' t3 = 'Inhuur ' c1 = Qt.darkBlue c2 = Qt.darkRed ysch = 30000000 elif keuze == '6': s1 = 18 s2 = 19 t1 = 'Diensten begroot' t2 = 'Diensten werkelijk' t3 = 'Diensten ' c1 = Qt.red c2 = Qt.blue ysch = 30000000 elif keuze == '7': s1 = 14 s2 = 15 t1 = 'Projektkosten begroot' t2 = 'Projektkosten werkelijk' t3 = 'Projektkosten ' c1 = Qt.darkYellow c2 = Qt.darkCyan ysch = 10000000 elif keuze == '8': y3 = [ 0, ] y3val = 0 x1 = [ 0, ] xval1 = 0 # prognose winst for teller in range(0, 53): y3val = y3val + bw_incr y3 = y3 + [(y3val)] xval1 = xval1 + 1 x1 = x1 + [(xval1)] s1 = 20 s2 = 20 t1 = 'Bruto winst prognose' t2 = 'Bruto winst actueel' t3 = 'Bruto winst - prognose / aktueel ' c1 = Qt.darkCyan c2 = Qt.darkMagenta ysch = 20000000 elif keuze == '9': s1 = 6 s2 = 4 t1 = 'Onderhandenwerk' t2 = 'Betaald bedrag' t3 = 'Onderhandenwerk - Betaald bedrag ' c1 = Qt.yellow c2 = Qt.green ysch = 160000000 elif keuze == 'A': y4 = [ 0, ] y4val = 0 x2 = [ 0, ] xval2 = 0 #prognose omzet for teller in range(0, 53): y4val = y4val + bo_incr y4 = y4 + [(y4val)] xval2 = xval2 + 1 x2 = x2 + [(xval2)] s1 = 7 s2 = 7 t1 = 'Omzet prognose' t2 = 'Omzet aktueel' t3 = 'Omzet ' c1 = Qt.red c2 = Qt.blue ysch = 160000000 elif keuze == 'B': s1 = 20 s2 = 5 t1 = 'Bruto winst werkelijk' t2 = 'Meerminderwerk' t3 = 'Bruto winst werkelijk / Meerminderwerk ' c1 = Qt.darkRed c2 = Qt.darkBlue ysch = 30000000 x = [ 0, ] y1 = [ 0, ] y2 = [ 0, ] idx = 0 yval1 = 0 yval2 = 0 for row in rpres: yval1 = y1[idx] + row[s1] y1 = y1 + [(yval1)] yval2 = y2[idx] + row[s2] y2 = y2 + [(yval2)] x = x + [(int(row[1][4:]))] idx += 1 series1 = QLineSeries() if keuze == '8': for t, val in zip(x1, y3): series1.append(int(t), val) elif keuze == 'A': for t, val in zip(x2, y4): series1.append(int(t), val) else: for t, val in zip(x, y1): series1.append(int(t), val) series2 = QLineSeries() for t, val in zip(x, y2): series2.append(int(t), val) chart = QChart() chart.addSeries(series1) chart.addSeries(series2) series1.setColor(QColor(c1)) series2.setColor(QColor(c2)) series1.setName(t1) series2.setName(t2) chart.legend().setVisible(True) font = QFont() font.setPixelSize(22) chart.setTitleFont(font) chart.setTitle(t3 + jaar) chart.setTitleBrush(QBrush(Qt.black)) chart.legend().setLabelBrush(QColor(Qt.black)) axisX = QCategoryAxis() axisY = QCategoryAxis() axisX.setTitleText('Jaar ' + jaar + ' - Weeknummers') axisX.setTitleBrush(QBrush(Qt.black)) font = QFont("Sans Serif") axisX.setTitleFont(font) axisPen = QPen(QColor(100, 100, 100)) # 100,100,100 axisPen.setWidth(3) axisX.setLinePen(axisPen) axisY.setLinePen(axisPen) axisBrush = QBrush(Qt.black) axisX.setLabelsBrush(axisBrush) axisY.setLabelsBrush(axisBrush) axisX.setGridLineVisible(False) axisY.setGridLineVisible(True) axisX.setShadesBrush(QBrush(QColor(245, 245, 245))) axisX.setShadesVisible(True) for x in range(1, 54): axisX.append(jaar + "-" + ("0" + str(x))[-2:], x) axisX.setRange(0, 53) axisX.setLabelsAngle(-90) axisY = QValueAxis() axisY.setTickCount(33) axisY.setTitleText("Bedragen in Euro") axisY.setTitleFont(font) axisY.setLabelFormat('%d') axisY.setTitleBrush(QBrush(Qt.black)) axisY.setRange(0, ysch) #disable for automatic Y scale #axisY.applyNiceNumbers() #enable by automatic Y scale Lfont = QFont("Sans Serif") Dfont = QFont("Sans Serif") Lfont.setPixelSize(10) Dfont.setPixelSize(10) axisX.setLabelsFont(Dfont) axisY.setLabelsFont(Lfont) axisPen = QPen(QColor('black')) axisPen = QPen() axisPen.setWidth(2) axisX.setLinePen(axisPen) axisX.setLabelsColor(QColor('black')) axisY.setLinePen(axisPen) axisY.setLabelsColor(QColor('black')) chart.addAxis(axisX, Qt.AlignBottom) series1.attachAxis(axisX) axisX.setLabelsAngle(-90) chart.addAxis(axisY, Qt.AlignLeft) series1.attachAxis(axisY) series2.attachAxis(axisY) self.chartView = QChartView(chart) self.chartView.setRenderHint(QPainter.Antialiasing) buttonPreview = QPushButton('Afdrukvoorbeeld') buttonPreview.clicked.connect(self.handle_preview) buttonPreview.setStyleSheet( "color: black; background-color: gainsboro") buttonPrint = QPushButton('Printen') buttonPrint.clicked.connect(self.handle_print) buttonPrint.setStyleSheet( "color: black; background-color: gainsboro") buttonSluit = QPushButton('Sluiten') buttonSluit.clicked.connect(lambda: sluit(self, m_email)) buttonSluit.setStyleSheet( "color: black; background-color: gainsboro") grid.addWidget(self.chartView, 0, 0, 0, 3) grid.addWidget(buttonSluit, 1, 0) grid.addWidget(buttonPrint, 1, 1) grid.addWidget(buttonPreview, 1, 2) self.setLayout(grid) self.setGeometry(200, 40, 1395, 930)
def bars_stacked(name, table_df, x_bottom_cols, y_left_cols, y_right_cols, legend_labels, tick_count): """ 柱形堆叠图 :param name: 图表名称 :param table_df: 用于画图的pandas DataFrame对象 :param x_bottom_cols: 下轴列索引列表 :param y_left_cols: 左轴列索引列表 :param y_right_cols: 右轴列索引列表 :param legend_labels: 图例名称标签列表 :param tick_count: 横轴刻度标签数 :return: QChart实例 """ """ 过滤轴 """ for y_left_col in y_left_cols: if is_datetime64_any_dtype(table_df[y_left_col]): # 如果是时间轴 y_left_cols.remove(y_left_col) for y_right_col in y_right_cols: if is_datetime64_any_dtype(table_df[y_right_col]): # 如果是时间轴 y_right_cols.remove(y_right_col) # 将x轴转为字符串 x_bottom = x_bottom_cols[0] # x轴列 if is_datetime64_any_dtype(table_df[x_bottom]): # 如果x轴是时间轴 table_df[x_bottom] = table_df[x_bottom].apply( lambda x: x.strftime('%Y-%m-%d')) else: # x轴非时间轴 table_df[x_bottom] = table_df[x_bottom].apply(lambda x: str(x)) font = QFont() # 轴文字风格 font.setPointSize(7) # 轴标签文字大小 chart = QChart() # 图表实例 chart.layout().setContentsMargins(0, 0, 0, 0) # chart的外边距 chart.setMargins(QMargins(15, 5, 15, 0)) # chart内边距 chart.setTitle(name) # chart名称 """ x轴 """ axis_x_bottom = QCategoryAxis( chart, labelsPosition=QCategoryAxis.AxisLabelsPositionOnValue) axis_x_bottom.setLabelsAngle(-90) # 逆时针旋转90度 axis_x_bottom.setLabelsFont(font) # 设置字体样式 axis_x_bottom.setGridLineVisible(False) # 竖向连接线不可见 # chart.addAxis(axis_x_bottom, Qt.AlignBottom) # 加入坐标x轴 has_x_labels = False # 收集x轴刻度的开关 chart.x_labels = list() # 绑定chart一个x轴的刻度列表 """ 左Y轴 """ axis_y_left = QValueAxis() axis_y_left.setLabelsFont(font) axis_y_left.setLabelFormat('%i') chart.addAxis(axis_y_left, Qt.AlignLeft) # 图表加入左轴 """ 右Y轴 """ axis_y_right = QValueAxis() axis_y_right.setLabelsFont(font) axis_y_right.setLabelFormat('%.2f') chart.addAxis(axis_y_right, Qt.AlignRight) # 记录各轴的最值 x_bottom_min, x_bottom_max = 0, table_df.shape[0] y_left_min, y_left_max = 0, 0 y_right_min, y_right_max = 0, 0 # 柱形图 left_bars = QBarSeries() """ 根据左轴画柱形 """ for y_left_col in y_left_cols: # 根据左轴画折线 # 计算做轴的最值用于设置范围 table_df[y_left_col] = table_df[y_left_col].apply( covert_float) # y轴列转为浮点数值 # 获取最值 y_min, y_max = table_df[y_left_col].min(), table_df[y_left_col].max() if y_min < y_left_min: y_left_min = y_min if y_max > y_left_max: y_left_max = y_max # 取得图表的源数据作柱形 left_bar_data = table_df.iloc[:, [x_bottom, y_left_col]] bar = QBarSet(legend_labels[y_left_col]) bar.setPen(QPen(Qt.transparent)) # 设置画笔轮廓线透明(数据量大会出现空白遮住柱形) for index, point_item in enumerate(left_bar_data.values.tolist()): bar.append(point_item[1]) if not has_x_labels: chart.x_labels.append(point_item[0]) has_x_labels = True # 关闭添加轴标签 left_bars.append(bar) # 柱形加入系列 left_bars.attachAxis(axis_y_left) # 左轴的范围 axis_y_left.setRange(y_left_min, y_left_max) """ 根据右轴画柱形 """ right_bars = QBarSeries() for y_right_col in y_right_cols: # 根据右轴画柱形 # 计算做轴的最值用于设置范围 table_df[y_right_col] = table_df[y_right_col].apply( covert_float) # y轴列转为浮点数值 # 获取最值 y_min, y_max = table_df[y_right_col].min(), table_df[y_right_col].max() if y_min < y_right_min: y_right_min = y_min if y_max > y_right_max: y_right_max = y_max # 取得图线的源数据作折线图 right_bar_data = table_df.iloc[:, [x_bottom, y_right_col]] bar = QBarSet(legend_labels[y_right_col]) bar.setPen(QPen(Qt.transparent)) for position_index, point_item in enumerate( right_bar_data.values.tolist()): bar.append(point_item[1]) # 取出源数据后一条线就2列数据 right_bars.append(bar) right_bars.attachAxis(axis_x_bottom) right_bars.attachAxis(axis_y_right) # 右轴范围 axis_y_right.setRange(y_right_min, y_right_max) chart.addSeries(left_bars) # 左轴的柱形图加入图表 # print(right_bars.count()) if right_bars.count() != 0: # 为空时加入会导致空位 chart.addSeries(right_bars) chart.setAxisX(axis_x_bottom, left_bars) # 关联设置x轴 # 横轴标签设置 x_bottom_interval = int(x_bottom_max / (tick_count - 1)) if x_bottom_interval == 0: for i in range(0, x_bottom_max): axis_x_bottom.append(chart.x_labels[i], i) else: for i in range(0, x_bottom_max, x_bottom_interval): axis_x_bottom.append(chart.x_labels[i], i) chart.legend().setAlignment(Qt.AlignBottom) return chart
def initChart(self): series = QLineSeries() data = [ QPoint(0, 4), QPoint(3, 2), QPoint(7, 7), QPoint(9, 10), QPoint(12, 17), QPoint(17, 9), QPoint(20, 22), QPoint(22, 2), QPoint(28, 13) ] series.append(data) # creating chart object chart = QChart() chart.legend().hide() chart.addSeries(series) pen = QPen(QColor(0, 0, 128)) pen.setWidth(3) series.setPen(pen) font = QFont("Open Sans") font.setPixelSize(40) font.setBold(True) chart.setTitleFont(font) chart.setTitleBrush(QBrush(Qt.yellow)) chart.setTitle("Custom Chart Demo") backgroundGradient = QLinearGradient() backgroundGradient.setStart(QPoint(0, 0)) backgroundGradient.setFinalStop(QPoint(0, 1)) backgroundGradient.setColorAt(0.0, QColor(175, 201, 182)) backgroundGradient.setColorAt(1.0, QColor(51, 105, 66)) backgroundGradient.setCoordinateMode(QGradient.ObjectBoundingMode) chart.setBackgroundBrush(backgroundGradient) plotAreaGraident = QLinearGradient() plotAreaGraident.setStart(QPoint(0, 1)) plotAreaGraident.setFinalStop(QPoint(1, 0)) plotAreaGraident.setColorAt(0.0, QColor(222, 222, 222)) plotAreaGraident.setColorAt(1.0, QColor(51, 105, 66)) plotAreaGraident.setCoordinateMode(QGradient.ObjectBoundingMode) chart.setPlotAreaBackgroundBrush(plotAreaGraident) chart.setPlotAreaBackgroundVisible(True) # customize axis axisX = QCategoryAxis() axisY = QCategoryAxis() labelFont = QFont("Open Sans") labelFont.setPixelSize(25) axisX.setLabelsFont(labelFont) axisY.setLabelsFont(labelFont) axisPen = QPen(Qt.white) axisPen.setWidth(2) axisX.setLinePen(axisPen) axisY.setLinePen(axisPen) axisBrush = QBrush(Qt.white) axisX.setLabelsBrush(axisBrush) axisY.setLabelsBrush(axisBrush) axisX.setRange(0, 30) axisX.append("low", 10) axisX.append("medium", 20) axisX.append("high", 30) axisY.setRange(0, 30) axisY.append("slow", 10) axisY.append("average", 20) axisY.append("fast", 30) axisX.setGridLineVisible(False) axisY.setGridLineVisible(False) chart.addAxis(axisX, Qt.AlignBottom) chart.addAxis(axisY, Qt.AlignLeft) series.attachAxis(axisX) series.attachAxis(axisY) self.chartView = QChartView(chart) self.chartView.setRenderHint(QPainter.Antialiasing)