class ChartView(QChartView,QChart): def __init__(self, *args, **kwargs): super(ChartView, self).__init__(*args, **kwargs) self.resize(800, 600) self.setRenderHint(QPainter.Antialiasing) # 抗锯齿 self.chart_init() self.timer_init() def timer_init(self): #使用QTimer,2秒触发一次,更新数据 self.timer = QTimer(self) self.timer.timeout.connect(self.drawLine) self.timer.start(100) def chart_init(self): self.chart = QChart() self.series = QScatterSeries() #设置曲线名称 self.series.setName("实时数据") self.series.setColor(QColor(255,0,0)) self.series.setMarkerSize(20.0) self.series.setPen(QPen(QtCore.Qt.PenStyle.NoPen)) #把曲线添加到QChart的实例中 self.chart.addSeries(self.series) #声明并初始化X轴,Y轴 self.dtaxisX = QDateTimeAxis() self.vlaxisY = QValueAxis() #设置坐标轴显示范围 self.dtaxisX.setMin(QDateTime.currentDateTime().addSecs(-300*1)) self.dtaxisX.setMax(QDateTime.currentDateTime().addSecs(0)) self.vlaxisY.setMin(0) self.vlaxisY.setMax(1500) #设置X轴时间样式 self.dtaxisX.setFormat("MM月dd hh:mm:ss") #设置坐标轴上的格点 self.dtaxisX.setTickCount(6) self.vlaxisY.setTickCount(11) #设置坐标轴名称 self.dtaxisX.setTitleText("时间") self.vlaxisY.setTitleText("量程") #设置网格不显示` #把坐标轴添加到chart中 self.chart.addAxis(self.dtaxisX,Qt.AlignBottom) self.chart.addAxis(self.vlaxisY,Qt.AlignLeft) #把曲线关联到坐标轴 self.series.attachAxis(self.dtaxisX) self.series.attachAxis(self.vlaxisY) self.setChart(self.chart) def drawLine(self): #获取当前时间 bjtime = QDateTime.currentDateTime() #更新X轴坐标 self.dtaxisX.setMin(QDateTime.currentDateTime().addSecs(-300*1)) self.dtaxisX.setMax(QDateTime.currentDateTime().addSecs(0)) #当曲线上的点超出X轴的范围时,移除最早的点 if(self.series.count()>149): self.series.removePoints(0,self.series.count()-149) #产生随即数 yint = random.randint(0,1500) #添加数据到曲线末端 self.series.append(bjtime.toMSecsSinceEpoch(),yint)
def make_axis(self): if self.x_time_scaled: axis_x = QDateTimeAxis() axis_x.setFormat("yyyy-MM-dd HH:mm:ss") axis_x.setTitleText("Время") else: axis_x = QValueAxis() axis_x.setTitleText(self.x_name) if self.x_min: axis_x.setMin(self.x_min) if self.x_max: axis_x.setMax(self.x_max) axis_x.setLabelsAngle(self.x_label_angle) axis_x.setTickCount(self.x_tick_num) axis_y = QValueAxis() if self.y_min: axis_y.setMin(self.y_min) if self.y_max: axis_y.setMax(self.y_max) axis_y.setTitleText(self.y_name) axis_y.setTickCount(self.y_tick_num) axis_y.setLabelsAngle(self.y_label_angle) return axis_x, axis_y
def _init_chart(self) -> None: series = QBarSeries() axis_x = QBarCategoryAxis() axis_y = QValueAxis() data_set = defaultdict(int) for title, money in self.base: data_set[title] += money for title, money in data_set.items(): bar = QBarSet(title) axis_x.append(title) bar.append(money) series.append(bar) # self.chart = QChart() self.chart.addSeries(series) self.chart.setAnimationOptions(QChart.SeriesAnimations) # series.attachAxis(axis_x) self.chart.addAxis(axis_x, Qt.AlignBottom) axis_y.setRange(0, max(data_set.values())) axis_y.setTickCount(11) self.chart.addAxis(axis_y, Qt.AlignLeft) series.attachAxis(axis_y) # self.chart.legend().setVisible(True) self.chart.legend().setAlignment(Qt.AlignBottom)
class QuarterlyLineDiagram(QChart): """Builds a QChart line chart with transaction data from two latest years""" def __init__(self, qseries_list, title): super(QuarterlyLineDiagram, self).__init__() # Setup quarterly axis self.x_axis = QCategoryAxis() self.y_axis = QValueAxis() self.y_axis.setTickCount(6) self.x_axis.setMin(1) self.x_axis.setMax(366) self.x_axis.append("Q1", 91) self.x_axis.append("Q2", 182) self.x_axis.append("Q3", 274) self.x_axis.append("Q4", 365) # Setup chart self.setTitle(title) for series in qseries_list: self.addSeries(series) self.createDefaultAxes() # autoscale y-axis self.setAxisX(self.x_axis) # use predefined quarterly x-axis self.setAnimationOptions(QChart.SeriesAnimations) self.legend().setVisible(True) self.legend().setAlignment(Qt.AlignBottom)
def __createChart(self): self.__chart = QChart() self.__chart.setTitle("简单函数曲线") self.ui.chartView.setChart(self.__chart) self.ui.chartView.setRenderHint(QPainter.Antialiasing) series0 = QLineSeries() series0.setName("Sin曲线") series1 = QLineSeries() series1.setName("Cos曲线") self.__curSeries=series0 #当前序列 pen=QPen(Qt.red) pen.setStyle(Qt.DotLine) #SolidLine, DashLine, DotLine, DashDotLine pen.setWidth(2) series0.setPen(pen) #序列的线条设置 pen.setStyle(Qt.SolidLine) #SolidLine, DashLine, DotLine, DashDotLine pen.setColor(Qt.blue) series1.setPen(pen) #序列的线条设置 self.__chart.addSeries(series0) self.__chart.addSeries(series1) axisX = QValueAxis() self.__curAxis=axisX #当前坐标轴 axisX.setRange(0, 10) #设置坐标轴范围 axisX.setLabelFormat("%.1f") #标签格式 axisX.setTickCount(11) #主分隔个数 axisX.setMinorTickCount(4) axisX.setTitleText("time(secs)") #标题 axisX.setGridLineVisible(True) axisX.setMinorGridLineVisible(False) axisY = QValueAxis() axisY.setRange(-2, 2) axisY.setLabelFormat("%.2f") #标签格式 axisY.setTickCount(5) axisY.setMinorTickCount(4) axisY.setTitleText("value") axisY.setGridLineVisible(True) axisY.setMinorGridLineVisible(False) ## self.__chart.setAxisX(axisX, series0) #添加X坐标轴 ## self.__chart.setAxisX(axisX, series1) #添加X坐标轴 ## self.__chart.setAxisY(axisY, series0) #添加Y坐标轴 ## self.__chart.setAxisY(axisY, series1) #添加Y坐标轴 ##另一种实现设置坐标轴的方法 self.__chart.addAxis(axisX,Qt.AlignBottom) #坐标轴添加到图表,并指定方向 self.__chart.addAxis(axisY,Qt.AlignLeft) series0.attachAxis(axisX) #序列 series0 附加坐标轴 series0.attachAxis(axisY) series1.attachAxis(axisX) #序列 series1 附加坐标轴 series1.attachAxis(axisY)
def set_x_aix(self, years: []) -> QValueAxis: # x轴坐标——年份 x_aix = QValueAxis() x_aix.setRange(years[0], years[-1]) x_aix.setLabelFormat('%d') x_aix.setGridLineVisible(True) x_aix.setTickCount(len(years)) x_aix.setMinorTickCount(5) # 每两个月一个小分级 return x_aix
def update_axes(self): # Get and remove all axes for axis in self.chart.axes(): self.chart.removeAxis(axis) # Create new axes # Create axis X # axisX = QDateTimeAxis() # axisX.setTickCount(5) # axisX.setFormat("dd MMM yyyy") # axisX.setTitleText("Date") # self.chart.addAxis(axisX, Qt.AlignBottom) # axisX.rangeChanged.connect(self.axis_range_changed) axisX = QValueAxis() axisX.setTickCount(10) axisX.setLabelFormat("%li") axisX.setTitleText("Seconds") self.chart.addAxis(axisX, Qt.AlignBottom) # axisX.rangeChanged.connect(self.axis_range_changed) # Create axis Y axisY = QValueAxis() axisY.setTickCount(5) axisY.setLabelFormat("%.3f") axisY.setTitleText("Values") self.chart.addAxis(axisY, Qt.AlignLeft) # axisY.rangeChanged.connect(self.axis_range_changed) ymin = None ymax = None # Attach axes to series, find min-max for series in self.chart.series(): series.attachAxis(axisX) series.attachAxis(axisY) vect = series.pointsVector() for i in range(len(vect)): if ymin is None: ymin = vect[i].y() ymax = vect[i].y() else: ymin = min(ymin, vect[i].y()) ymax = max(ymax, vect[i].y()) # Update range # print('min max', ymin, ymax) if ymin is not None: axisY.setRange(ymin, ymax) # Make the X,Y axis more readable axisX.applyNiceNumbers()
class Window(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("PyQtChart Demo") self.setGeometry(500, 275, 650, 500) self.show() self.createLineChart() def createLineChart(self): self.font = QFont("Arial") self.font.setPixelSize(16) self.font.setBold(True) self.pen = QPen(QColor(0, 153, 0)) self.pen.setWidth(3) self.series = QLineSeries(self) self.series.setPen(self.pen) self.x = np.arange(0, 2 * np.pi, 0.01) for i in self.x: self.series.append(i, np.sin(i)) self.chart = QChart() self.chart.addSeries(self.series) self.chart.setAnimationOptions(QChart.SeriesAnimations) self.chart.setTitleFont(self.font) self.chart.setTitleBrush(QBrush(Qt.blue)) self.chart.setTitle("Line Chart Demo") self.chart.legend().setVisible(True) self.chart.legend().setAlignment(Qt.AlignBottom) self.chartview = QChartView(self.chart) self.chartview.setRenderHint(QPainter.Antialiasing) self.axisX = QValueAxis() self.axisX.setRange(0, 2 * np.pi) self.axisX.setTickCount(6) self.axisX.setLabelFormat("%.1f") self.axisX.setTitleText("x") self.axisY = QValueAxis() self.axisY.setRange(0, 100) self.axisY.setLabelFormat("%d") self.axisY.setTitleText("sin(x)") self.chart.addAxis(self.axisX, Qt.AlignBottom) self.chart.addAxis(self.axisY, Qt.AlignLeft) self.setCentralWidget(self.chartview)
def agg_glycoforms(self) -> None: """ Display glycoform data in the corresponding chart view. :return: nothing :rtype: None """ # aggregate "other" abundances if self.cbAggGlycoforms.isChecked(): agg_abundance = ( self.glycoforms.iloc[self.sbAggGlycoforms.value():].sum()) self.glycoforms_agg = ( self.glycoforms.iloc[:self.sbAggGlycoforms.value()].append( pd.Series(agg_abundance, index=[self.tr("other")]))) else: self.glycoforms_agg = self.glycoforms # extract x- and y-values from series x_values = [str(i) for i in self.glycoforms_agg.index] y_values = [a.nominal_value for a in self.glycoforms_agg] # assemble the chart bar_set = QBarSet("glycoform abundance") bar_set.append(y_values) bar_set.setColor(QColor("#2c7fb8")) bar_set.hovered.connect(self.update_glycoform_label) bar_series = QBarSeries() bar_series.append(bar_set) x_axis = QBarCategoryAxis() x_axis.append(x_values) x_axis.setTitleVisible(False) x_axis.setLabelsAngle(270) range_max = max(self.glycoforms_agg).nominal_value range_max = math.ceil(range_max / 20) * 20 tick_count = range_max // 20 + 1 y_axis = QValueAxis() y_axis.setRange(0, range_max) y_axis.setTickCount(tick_count) y_axis.setTitleText(self.tr("abundance")) y_axis.setLabelFormat("%d") chart = QChart() chart.addSeries(bar_series) chart.setAxisX(x_axis, bar_series) chart.setAxisY(y_axis, bar_series) chart.legend().setVisible(False) chart.setBackgroundRoundness(0) chart.layout().setContentsMargins(0, 0, 0, 0) chart.setMargins(QMargins(5, 5, 5, 5)) self.cvGlycoforms.setChart(chart)
class CharPlotWidget(QChartView): def __init__(self, parent=None): super().__init__(parent=parent) self.setRenderHint(QPainter.Antialiasing) self._chart = self.chart() self._axis_x = QValueAxis() self._axis_y = QValueAxis() self.series = QLineSeries(self) self._chart.addSeries(self.series) self._chart.addAxis(self._axis_x, Qt.AlignBottom) self._chart.addAxis(self._axis_y, Qt.AlignLeft) self.series.attachAxis(self._axis_x) self.series.attachAxis(self._axis_y) self._axis_x.setTickCount(5) self._axis_x.setRange(0, 10) self._axis_y.setTickCount(5) self._axis_y.setRange(0, 10) self._chart.legend().hide() def plot(self, xs, ys): self.series.replace([QPointF(x, y) for x, y in zip(xs, ys)]) @property def axes_titles(self): return self._axis_x.titleText(), self._axis_y.titleText() @axes_titles.setter def axes_titles(self, value): x, y = value self._axis_x.setTitleText(x) self._axis_y.setTitleText(y) @property def title(self): return self._chart.title() @title.setter def title(self, value): self._chart.setTitle(value) @property def legend(self): return self._chart.legend()
def __createChart(self): self.__chart = QChart() self.ui.chartView.setChart(self.__chart) self.__chart.legend().setVisible(False) #隐藏图例 self.__chart.setMargins(QMargins(0, 0, 0, 0)) #把间距设置到最小 #初始化线条数组 series = [QLineSeries() for _ in range(15)] color = [ '#FF88C2', '#FF8888', '#FFA488', '#FFBB66', '#FFDD55', '#FFFF77', '#DDFF77', '#BBFF66', '#66FF66', '#77FFCC', '#77FFEE', '#66FFFF', '#77DDFF', '#99BBFF', '#9999FF' ] #设置线条颜色形状 pen = QPen() pen.setStyle(Qt.SolidLine) pen.setWidth(2) for i in range(15): pen.setColor(QColor(color[i])) series[i].setPen(pen) #向表格添加线条 for i in range(15): self.__chart.addSeries(series[i]) #设置坐标轴 axisX = QValueAxis() #self.__curAxis=axisX #当前坐标轴 axisX.setRange(0, 200) #设置坐标轴范围 axisX.setLabelFormat("%d") #标签格式 axisX.setTickCount(5) #主分隔个数 axisX.setMinorTickCount(4) axisX.setGridLineVisible(True) axisX.setMinorGridLineVisible(False) axisY = QValueAxis() axisY.setRange(0, 1024) axisY.setLabelFormat("%d") #标签格式 axisY.setTickCount(5) axisY.setMinorTickCount(4) axisY.setGridLineVisible(True) axisY.setMinorGridLineVisible(False) self.__chart.addAxis(axisX, Qt.AlignBottom) #坐标轴添加到图表,并指定方向 self.__chart.addAxis(axisY, Qt.AlignLeft) for i in range(15): series[i].attachAxis(axisX) series[i].attachAxis(axisY)
def crearGraficoBarras(self): paises = [ "EEUU", "China", "Japon", "Alemania", "Reino Unido", "Resto del mundo" ] valores = [24.32, 14.85, 8.91, 12.54, 7.85, 31.53] colores = [ Qt.blue, Qt.red, Qt.darkYellow, Qt.gray, Qt.black, Qt.darkCyan ] grafico = QChart() grafico.setMargins(QMargins(30, 30, 30, 30)) grafico.setTheme(QChart.ChartThemeLight) grafico.setTitle("% Distribución del PIB global") grafico.setAnimationOptions(QChart.SeriesAnimations) for i in range(len(paises)): series = QBarSeries() barSet = QBarSet(paises[i]) barSet.setColor(colores[i]) barSet.setLabelColor(Qt.yellow) barSet.append(valores[i]) series.append(barSet) series.setLabelsVisible(True) series.setLabelsAngle(-90) # series.setLabelsPrecision(2) series.setLabelsFormat("@value %") series.setLabelsPosition(QAbstractBarSeries.LabelsCenter) grafico.addSeries(series) axisX = QBarCategoryAxis() axisX.append(paises) axisY = QValueAxis() axisY.setRange(0, 31.53) axisY.setTickCount(10) axisY.setLabelFormat("%.2f %") grafico.createDefaultAxes() grafico.setAxisX(axisX, None) grafico.setAxisY(axisY, None) grafico.legend().setVisible(True) grafico.legend().setAlignment(Qt.AlignBottom) return grafico
class ChartView(QChartView): def __init__(self): QChartView.__init__(self) #self.resize(300, 300) self.setRenderHint(QPainter.Antialiasing) # 抗锯齿 self.chart = QChart() self.seriesAcc = QLineSeries() self.seriesAcc.setName(CONF.leftUpNames[0]) self.chart.addSeries(self.seriesAcc) #声明并初始化X轴,Y轴 self.dtaxisX = QValueAxis() self.vlaxisY = QValueAxis() #设置坐标轴显示范围 self.dtaxisX.setMin(0) #self.dtaxisX.setMax(100) self.vlaxisY.setMin(0) #self.vlaxisY.setMax(100) self.dtaxisX.setTickCount(3) self.vlaxisY.setTickCount(3) #设置坐标轴名称 self.dtaxisX.setTitleText(CONF.leftUpNames[1]) self.vlaxisY.setTitleText(CONF.leftUpNames[2]) #设置网格不显示 self.vlaxisY.setGridLineVisible(False) #把坐标轴添加到chart中 self.chart.addAxis(self.dtaxisX, Qt.AlignBottom) self.chart.addAxis(self.vlaxisY, Qt.AlignLeft) self.seriesAcc.attachAxis(self.dtaxisX) self.seriesAcc.attachAxis(self.vlaxisY) self.initUI() def initUI(self): self.backend = BackendThread() self.backend.update_line.connect(self.handleLine) self.backend.start() def handleLine(self, data): if data[0] == 0: self.seriesAcc.clear() else: self.dtaxisX.setMax(data[0]) self.vlaxisY.setMax(data[0]) self.seriesAcc.clear() self.seriesAcc.append(0, 0) self.seriesAcc.append(data[0], data[1]) self.setChart(self.chart)
def set_y_aix(self, areas: []) -> QValueAxis: # y轴坐标——面积 ma = [] for i in range(0, len(areas)): m = max(areas[i]) ma.append(m) bound = max(ma) y_aix = QValueAxis() y_aix.setRange(0, int(bound)) y_aix.setLabelFormat('%d') y_aix.setGridLineVisible(True) y_aix.setTickCount(11) y_aix.setMinorTickCount(4) return y_aix
class DynamicSpline(QChart): def __init__(self): super().__init__() self.m_step = 0 self.m_x = 2 self.m_y = 1 # Инициализировать изображение self.series = QSplineSeries(self) red_pen = QPen(Qt.red) red_pen.setWidth(2) self.series.setPen(red_pen) self.axisX = QValueAxis() self.axisY = QValueAxis() self.series.append(self.m_x, self.m_y) self.addSeries(self.series) self.addAxis(self.axisX, Qt.AlignBottom) self.addAxis(self.axisY, Qt.AlignLeft) self.series.attachAxis(self.axisX) self.series.attachAxis(self.axisY) self.axisX.setTickCount(5) self.axisX.setRange(0, 10) self.axisY.setRange(0, 100) self.timer = QTimer(self) self.timer.setInterval(1000) self.timer.timeout.connect(self.handleTimeout) self.timer.start() def handleTimeout(self): x = self.plotArea().width() / self.axisX.tickCount() y = (self.axisX.max() - self.axisX.min()) / self.axisX.tickCount() self.m_x += y # В PyQt 5.11.3 и выше, QRandomGenerator.global() был переименован в global_() try: self.m_y=db_wrk() except : self.m_y = QRandomGenerator.global_().bounded(50) self.series.append(self.m_x, self.m_y) self.scroll(x, 0) if self.m_x >= 10: self.timer.stop() def db_wrk(): return m_y
class CpuLineChart(QChart): def __init__(self, *args, **kwargs): super(CpuLineChart, self).__init__(*args, **kwargs) self.m_count = 10 # 隐藏图例 self.legend().hide() self.m_series = QSplineSeries(self) # 设置画笔 self.m_series.setPen(QPen(QColor('#3B8CFF'), 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.addSeries(self.m_series) # x轴 self.m_axisX = QDateTimeAxis(self) self.m_axisX.setTickCount(self.m_count + 1) # 设置刻度数量 self.m_axisX.setFormat('hh:mm:ss') # 设置时间显示格式 now = QDateTime.currentDateTime() # 前10秒到现在 self.m_axisX.setRange(now.addSecs(-self.m_count), now) self.addAxis(self.m_axisX, Qt.AlignBottom) self.m_series.attachAxis(self.m_axisX) # y轴 self.m_axisY = QValueAxis(self) self.m_axisY.setLabelFormat('%d') # 设置文本格式 self.m_axisY.setMinorTickCount(4) # 设置小刻度线的数目 self.m_axisY.setTickCount(self.m_count + 1) self.m_axisY.setRange(0, 100) self.addAxis(self.m_axisY, Qt.AlignLeft) self.m_series.attachAxis(self.m_axisY) # 填充11个初始点,注意x轴 需要转为秒的时间戳 self.m_series.append( [QPointF(now.addSecs(-i).toMSecsSinceEpoch(), 0) for i in range(self.m_count, -1, -1)]) # 定时器获取数据 self.m_timer = QTimer() self.m_timer.timeout.connect(self.update_data) self.m_timer.start(1000) def update_data(self): value = cpu_percent() now = QDateTime.currentDateTime() self.m_axisX.setRange(now.addSecs(-self.m_count), now) # 重新调整x轴的时间范围 # 获取原来的所有点,去掉第一个并追加新的一个 points = self.m_series.pointsVector() points.pop(0) points.append(QPointF(now.toMSecsSinceEpoch(), value)) # 替换法速度更快 self.m_series.replace(points)
def setupChart(self): """Set up the GUI's graph line series type, chart instance, chart axes, and chart view widget.""" # Collect x and y data values from the CSV file x_values, y_values = self.loadCSVFile() # Create chart object chart = QChart() chart.setTitle( "Public Social Spending as a Share of GDP for Sweden, 1880 to 2016" ) chart.setAnimationOptions(QChart.SeriesAnimations) chart.legend().hide() # Hide the chart's legend line_series = QLineSeries() # Using line charts for this example #line_series.setPointLabelsVisible(True) #line_series.setPen(QColor(Qt.blue)) # Loop through corresponding x and y values and add them to the line chart for value in range(0, self.row_count - 1): line_series.append(x_values[value], y_values[value]) chart.addSeries(line_series) # Add line series to chart instance # Specify parameters for the x and y axes axis_x = QValueAxis() axis_x.setLabelFormat("%i") axis_x.setTickCount(10) axis_x.setRange(1880, 2016) chart.addAxis(axis_x, Qt.AlignBottom) line_series.attachAxis(axis_x) axis_y = QValueAxis() axis_y.setLabelFormat("%i" + "%") axis_y.setRange(0, 40) chart.addAxis(axis_y, Qt.AlignLeft) line_series.attachAxis(axis_y) # Create QChartView object for displaying the chart chart_view = QChartView(chart) chart_view.setRenderHint(QPainter.Antialiasing) # Create layout and set the layout for the window v_box = QVBoxLayout() v_box.addWidget(chart_view) self.setLayout(v_box)
class Chart(QChart): def __init__(self): super(QChart, self).__init__() self.m_timer = QTimer() self.m_series = None self.m_titles = [] self.m_axis = QValueAxis() self.m_step = None self.m_x = 5 self.m_y = 1 random.seed(QTime.currentTime().msec()) self.m_timer.timeout.connect(self.handleTimeout) self.m_timer.setInterval(1000) self.m_series = QSplineSeries(self) green = QPen(Qt.green) green.setWidth(3) self.m_series.setPen(green) self.m_series.append(self.m_x, self.m_y) self.addSeries(self.m_series) self.createDefaultAxes() self.setAxisX(self.m_axis, self.m_series) self.m_axis.setTickCount(5) self.axisX().setRange(0, 10) self.axisY().setRange(-5, 10) self.m_timer.start() @pyqtSlot() def handleTimeout(self): x = self.plotArea().width() / self.m_axis.tickCount() y = (self.m_axis.max() - self.m_axis.min()) / self.m_axis.tickCount() self.m_x += y self.m_y = random.randint(0, 5) - 2.5 self.m_series.append(self.m_x, self.m_y) self.scroll(x, 0) if self.m_x is 100: self.m_timer.stop()
def update_axes(self): # Get and remove all axes for axis in self.chart.axes(): self.chart.removeAxis(axis) # Create new axes # Create axis X axisx = QDateTimeAxis() axisx.setTickCount(5) axisx.setFormat("dd MMM yyyy hh:mm:ss") axisx.setTitleText("Date") self.chart.addAxis(axisx, Qt.AlignBottom) # Create axis Y axisY = QValueAxis() axisY.setTickCount(5) axisY.setLabelFormat("%.3f") axisY.setTitleText("Values") self.chart.addAxis(axisY, Qt.AlignLeft) # axisY.rangeChanged.connect(self.axis_range_changed) ymin = None ymax = None # Attach axes to series, find min-max for series in self.chart.series(): series.attachAxis(axisx) series.attachAxis(axisY) vect = series.pointsVector() # for i in range(len(vect)): for i, _ in enumerate(vect): if ymin is None: ymin = vect[i].y() ymax = vect[i].y() else: ymin = min(ymin, vect[i].y()) ymax = max(ymax, vect[i].y()) # Update range # print('min max', ymin, ymax) if ymin is not None: axisY.setRange(ymin, ymax)
def createChart(self): self.timeChart = QChart() titleFont = QFont() titleFont.setPixelSize(18) titleBrush = QBrush(QColor(0, 0, 255)) self.timeChart.setTitleFont(titleFont) self.timeChart.setTitleBrush(titleBrush) self.timeChart.setTitle('Signal (Past ' + str(self.maxPoints) + ' Samples)') # self.timeChart.addSeries(testseries) # self.timeChart.createDefaultAxes() self.timeChart.legend().hide() # Axis examples: https://doc.qt.io/qt-5/qtcharts-multiaxis-example.html newAxis = QValueAxis() newAxis.setMin(0) newAxis.setMax(self.maxPoints) newAxis.setTickCount(11) newAxis.setLabelFormat("%d") newAxis.setTitleText("Sample") self.timeChart.addAxis(newAxis, Qt.AlignBottom) newAxis = QValueAxis() newAxis.setMin(-100) newAxis.setMax(-10) newAxis.setTickCount(9) newAxis.setLabelFormat("%d") newAxis.setTitleText("dBm") self.timeChart.addAxis(newAxis, Qt.AlignLeft) chartBorder = Qt.darkGray self.timePlot = QChartView(self.timeChart, self) self.timePlot.setBackgroundBrush(chartBorder) self.timePlot.setRenderHint(QPainter.Antialiasing) self.timeSeries = QLineSeries() pen = QPen(Qt.yellow) pen.setWidth(2) self.timeSeries.setPen(pen) self.timeChart.addSeries(self.timeSeries) self.timeSeries.attachAxis(self.timeChart.axisX()) self.timeSeries.attachAxis(self.timeChart.axisY())
def __init__(self, data, type): super(BarChart, self).__init__() if type == self.BAR_CHART: self.brushes = (QColor(Qt.blue), QColor(Qt.red), QBrush(Qt.blue, Qt.Dense5Pattern), QBrush(Qt.red, Qt.Dense5Pattern)) self.series = QBarSeries() axisY = QValueAxis() axisY.setRange(0, 5) axisY.setTickCount(6) axisY.setLabelFormat(" ") self.addAxis(axisY, Qt.AlignLeft) elif type == self.PERCENT_CHART: self.brushes = (QColor(Qt.yellow), QColor(255, 127, 0), QColor(Qt.red)) self.series = QPercentBarSeries() self.setData(data) self.addSeries(self.series) self.series.attachAxis(self.axisX) if type == self.BAR_CHART: self.series.attachAxis(axisY)
class DynamicSpline(QChart): def __init__(self): super().__init__() self.m_step = 0 self.m_x = 5 self.m_y = 1 # 初始化图像 self.series = QSplineSeries(self) green_pen = QPen(Qt.red) green_pen.setWidth(3) self.series.setPen(green_pen) self.axisX = QValueAxis() self.axisY = QValueAxis() self.series.append(self.m_x, self.m_y) self.addSeries(self.series) self.addAxis(self.axisX, Qt.AlignBottom) self.addAxis(self.axisY, Qt.AlignLeft) self.series.attachAxis(self.axisX) self.series.attachAxis(self.axisY) self.axisX.setTickCount(5) self.axisX.setRange(0, 10) self.axisY.setRange(-5, 10) self.timer = QTimer(self) self.timer.setInterval(1000) self.timer.timeout.connect(self.handleTimeout) self.timer.start() def handleTimeout(self): x = self.plotArea().width() / self.axisX.tickCount() y = (self.axisX.max() - self.axisX.min()) / self.axisX.tickCount() self.m_x += y # 在PyQt5.11.3及以上版本中,QRandomGenerator.global()被重命名为global_() self.m_y = QRandomGenerator.global_().bounded(5) - 2.5 self.series.append(self.m_x, self.m_y) self.scroll(x, 0) if self.m_x >= 100: self.timer.stop()
class XChartProbit(QChart): def __init__(self, parent=None): super(QChart, self).__init__(parent) # Class Vars self.activeDistr = 'lognorm' self.knowndistr = distr._distrnames() self.data = dict() # Axis Setup self.axisX = QValueAxis() self.axisY = QValueAxis() self.axisX.setLabelsVisible(False) self.axisX.setTickCount(2) self.axisX.setTitleText("Series Fractional Probability") self.axisY.setTitleText("Value") self.setAxesMinMax(-3, 3, 0.01, 1.5) self.axisX.setMinorGridLineVisible(False) self.axisX.setGridLineVisible(False) # define the default grid colour to grey self.setGridColor(110, 110, 110) self.setActiveProbit(self.activeDistr) self.plotAreaChanged.connect(self.onPlotSizeChanged) # method needed for axes change to redraw grid lines def addLinearReg(self, seriesname): x = self.data[seriesname]['X'], y = self.data[seriesname][seriesname] # adds a linear regression line for a data set x,y slope, intercept, r_value, p_value, std_err = linregress(x, y) xmin = distr.distrppf(self.activeDistr, 0.01) xmax = distr.distrppf(self.activeDistr, 0.99) ymin = slope * xmin + intercept ymax = slope * xmax + intercept data = dict() data['X'] = [xmin, xmax] data['LinearReg'] = [ymin, ymax] lines = XLineSeries(data, xkey='X', openGL=True) self.addSeries(lines[0]) self.setAxes(lines[0]) def loadSeries(self, arr, name): # takes a list/array arr y = array(arr).copy() y.sort() self.data[name] = y self.redrawChart() def plotSeries(self, name): nsamp = len(self.data[name]) # add data to temport dictionary tdict = dict() if self.activeScale == 'log10': tdict[name] = log10(self.data[name]) elif self.activeScale == 'linear': tdict[name] = self.data[name] tdict['X'] = distr.distrppf(self.activeProbit, [ percentileofscore(self.data[name], self.data[name][i]) / 100.00001 for i in range(0, nsamp) ]) series = XScatterSeries(tdict, xkey='X', openGL=True) self.addSeries(series[0]) self.setAxes(series[0]) def _replotData(self): for key in self.data.keys(): self.pl def axesMinMax(self): # returns a length 4 list of the axes min and max values [x1,x2,y1,y2] return [ self.axisX.min(), self.axisX.max(), self.axisY.min(), self.axisY.max() ] def redrawChart(self): self.removeAllSeries() self._removeHorizontalGridLabels() self.resetAxes() self._drawVerticalGridLines() if self.activeScale == 'log10': self.axisY.setLabelsVisible(False) self.axisY.setTickCount(1) self.setTitle("Log Probit Plot") self.axisY.setMinorGridLineVisible(False) self.axisY.setGridLineVisible(False) self._drawHorizontalGridLine() self._drawHorizontalLabels() self._drawHorizontalGridlLabels() elif self.activeScale == 'linear': self.axisY.setLabelsVisible(True) self.axisY.setTickCount(10) self.setTitle("Probit Plot") self.axisY.setMinorGridLineVisible(True) self.axisY.setGridLineVisible(True) for serkey in self.data.keys(): self.plotSeries(serkey) def resetAxes(self): ymins = [] ymaxs = [] for key in self.data.keys(): ymins.append(min(self.data[key])) ymaxs.append(max(self.data[key])) try: ymin = min(ymins) ymax = max(ymaxs) except ValueError: ymin = 1.1 ymax = 2 xmin = distr.distrppf(self.activeProbit, 0.001) xmax = distr.distrppf(self.activeProbit, 0.999) if self.activeScale == 'linear': yscal = 0.1 * (ymax - ymin) self.setAxesMinMax(xmin, xmax, ymin - yscal, ymax + yscal) elif self.activeScale == 'log10': yscal = 0.1 * (log10(ymax) - log10(ymin)) self.setAxesMinMax(xmin, xmax, log10(ymin), log10(ymax)) #self.setAxesMinMax(xmin,xmax,log10(ymin)-yscal,log10(ymax)+yscal*0.1) def setGridColor(self, r, g, b): # sets the colour of the background grid self.gridcolor = QColor(r, g, b) def setActiveProbit(self, type): if type in self.knowndistr: self.activeDistr = type if type == 'norm': self.activeProbit = 'norm' self.activeScale = 'linear' elif type == 'lognorm': self.activeProbit = 'norm' self.activeScale = 'log10' #self.redrawChart() def setActiveScale(self, newscale): self.activeScale = newscale def setAxes(self, series): # assigns a series to the chart default axes self.setAxisX(self.axisX, series) self.setAxisY(self.axisY, series) def setAxesMinMax(self, x1, x2, y1, y2): # sets the min max values in X and Y self.axisX.setMin(x1) self.axisX.setMax(x2) self.axisY.setMin(y1) self.axisY.setMax(y2) def _drawHorizontalLabels(self): xmin = self.axisX.min() xmax = self.axisX.max() axisScale = 1 / (xmax - xmin ) # scaler for plotted axis (reduces to 0-1.0) # calculate probit values to scale from grid lines insert min and max values to scale correctly vlabx = distr.distrppf(self.activeProbit, self.vgridx) vlabx = insert(vlabx, 0, xmin) vlabx = insert(vlabx, len(vlabx), xmax) vlabx = ( vlabx - xmin ) * axisScale #scale the probit value to ratios of the Xaxis length paw = self.plotArea().width() pah = self.plotArea().height() #find the plot width and height # find plot bottom left corner X and Y pblx = self.plotArea().bottomLeft().x() pbly = self.plotArea().bottomLeft().y() # offset from axix by 10 pixels -> may need to automate this offset in future pbly_lab = pbly + 10 # calculate the position on the chart in x plane with which to place each label. pblx = [pblx + int(paw * x) for x in vlabx[1:-1]] try: self.hlabels except AttributeError: self.hlabels = [] for i, labx in enumerate( pblx): #run through labels and create and position them # label text based on P scale ltext = 'P' + '%02d' % round(100.0 * (1.0 - self.vgridx[i])) self.hlabels.append(self.scene().addText(ltext)) for i, labx in enumerate( pblx): #run through labels and create and position them self.hlabels[i].setPos( labx - 0.5 * self.hlabels[i].boundingRect().width(), pbly) #centre on tick marks def _drawVerticalGridLines(self): self.vgridx = arange(0.05, 1.0, 0.05) self.vgridx = insert(self.vgridx, 0, [0.01, 0.02]) self.vgridx = insert(self.vgridx, len(self.vgridx), [0.98, 0.99]) vgridy = [self.axisY.min(), self.axisY.max()] self.vgridseries = [] for val in self.vgridx: line = 'P' + '%02d' % round(100.0 * (1.0 - val)) tdict = { 'X': [distr.distrppf(self.activeProbit, val)] * 2, line: vgridy } self.vgridseries = self.vgridseries + XLineSeries( tdict, xkey='X', openGL=True) for i, line in enumerate(self.vgridseries): pen = line.pen() pen.setColor(self.gridcolor) pen.setWidthF(0.4), line.setPen(pen) line.setPointLabelsVisible(True) self.addSeries(line) self.setAxes(line) self.legend().markers(line)[0].setVisible(False) def _drawHorizontalGridLine(self): # calculate xmin and xmax points for lines to completely cross graph hgridx = [ distr.distrppf(self.activeProbit, 0.0001) - 1, distr.distrppf(self.activeProbit, 0.9999) + 1 ] # calculate log scale for lines y values self.hgridy = self._logrange(10**self.axisY.min(), 10**self.axisY.max(), base=10) self.hgridseries = [] # create a line series for each lines and add to list for val in self.hgridy: line = '%d' % val tdict = {'X': hgridx, line: [log10(val)] * 2} self.hgridseries = self.hgridseries + XLineSeries( tdict, xkey='X', openGL=True) # add each of the series to the grid with special formatting for i, line in enumerate(self.hgridseries): pen = line.pen() pen.setColor(self.gridcolor) pen.setWidthF(0.4), line.setPen(pen) self.addSeries(line) self.setAxes(line) self.legend().markers(line)[0].setVisible(False) def _drawHorizontalGridlLabels(self): ymin = self.axisY.min() ymax = self.axisY.max() axisScale = 1 / (ymax - ymin ) # scaler for plotted axis (reduces to 0-1.0) # calculate base10 values to scale from grid lines insert min and max values to scale correctly vlaby = log10(self.hgridy) vlaby = insert(vlaby, 0, ymin) vlaby = insert(vlaby, len(vlaby), ymax) vlaby = ( vlaby - ymin ) * axisScale # scale the probit value to ratios of the Xaxis length paw = self.plotArea().width() pah = self.plotArea().height() # find the plot width and height # find plot bottom left corner X and Y pblx = self.plotArea().bottomLeft().x() pbly = self.plotArea().bottomLeft().y() # offset from axix by 10 pixels -> may need to automate this offset in future pblx_lab = pblx - 10 # calculate the position on the chart in y plane with which to place each label. pbly = [pbly - int(pah * y) for y in vlaby[1:-1]] self.vlabels = [] for i, labx in enumerate( pbly): # run through labels and create and position them # label text based on P scale ltext = str(self.hgridy[i]) self.vlabels.append(self.scene().addText(ltext)) for i, laby in enumerate( pbly): #run through labels and create and position them # label text based on P scale self.vlabels[i].setPos( pblx - self.vlabels[i].boundingRect().width() - 10, laby - 0.5 * self.vlabels[i].boundingRect().height()) #centre on tick marks def _removeHorizontalGridLine(self): for ser in self.hgridseries: self.removeSeries(ser) def _removeVerticalGridLine(self): for ser in self.vgridseries: self.removeSeries(ser) def _removeHorizontalGridLabels(self): try: for lab in self.vlabels: self.scene().removeItem(lab) except AttributeError: pass def _logrange(self, min, max, base=10): if min <= 0: min += max / (base**10) y = 1 bpow = base if min < base: while min < bpow: y -= 1 bpow = pow(base, y) else: while min > bpow: y += 1 bpow = pow(base, y) out = array([]) while bpow < max: y += 1 bpown = pow(base, y) out = append(out, arange(bpow, bpown, bpow)) bpow = bpown i = 0 j = 0 for ind, val in enumerate(out): if val <= min: i = ind if val <= max: j = ind return out[i:j + 1] @pyqtSlot() def onPlotSizeChanged(self): #reset position of labels self.redrawChart()
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.initializeUI() def initializeUI(self): """Initialize the window and display its contents.""" self.setMinimumSize(1200, 600) self.setWindowTitle("3.1 - Data Visualization GUI") self.setupChart() self.setupToolsDockWidget() self.setupMenu() self.show() def setupChart(self): """Set up the GUI's graph series type, chart instance, chart axes, and chart view widget.""" random.seed(50) # Create seed for random numbers # Create the model instance and set the headers self.model = QStandardItemModel() self.model.setColumnCount(3) self.model.setHorizontalHeaderLabels(["Year", "Social Exp. %GDP", "Country"]) # Collect x and y data values and labels from the CSV file xy_data_and_labels = self.loadCSVFile() # Create the individual lists for x, y and labels values x_values, y_values, labels = [], [], [] # Append items to the corresponding lists for item in range(len(xy_data_and_labels)): x_values.append(xy_data_and_labels[item][0]) y_values.append(xy_data_and_labels[item][1]) labels.append(xy_data_and_labels[item][2]) # Remove all duplicates from the labels list using list comprehension. # This list will be used to create the labels in the chart's legend. set_of_labels = [] [set_of_labels.append(x) for x in labels if x not in set_of_labels] # Create chart object self.chart = QChart() self.chart.setTitle("Public Social Spending as a Share of GDP, 1880 to 2016") self.chart.legend().hide() # Hide legend at the start # Specify parameters for the x and y axes self.axis_x = QValueAxis() self.axis_x.setLabelFormat("%i") self.axis_x.setTickCount(10) self.axis_x.setRange(1880, 2016) self.chart.addAxis(self.axis_x, Qt.AlignBottom) self.axis_y = QValueAxis() self.axis_y.setLabelFormat("%i" + "%") self.axis_y.setRange(0, 40) self.chart.addAxis(self.axis_y, Qt.AlignLeft) # Create a Python dict to associate the labels with the individual line series series_dict = {} for label in set_of_labels: # Create labels from data and add them to a Python dictionary series_label = 'series_{}'.format(label) series_dict[series_label] = label # Create label value for each line series # For each of the keys in the dict, create a line series for keys in series_dict.keys(): # Use get() to access the corresponding value for a key label = series_dict.get(keys) # Create line series instance and set its name and color values line_series = QLineSeries() line_series.setName(label) line_series.setColor(QColor(random.randint(10, 254), random.randint(10, 254), random.randint(10, 254))) # Append x and y coordinates to the series for value in range(len(xy_data_and_labels)): if line_series.name() == xy_data_and_labels[value][2]: line_series.append(x_values[value], y_values[value]) # Create and add items to the model (for displaying the table) items = [QStandardItem(str(item)) for item in xy_data_and_labels[value]] color = line_series.pen().color() for item in items: item.setBackground(color) self.model.insertRow(value, items) self.chart.addSeries(line_series) line_series.attachAxis(self.axis_x) line_series.attachAxis(self.axis_y) # Create QChartView object for displaying the chart self.chart_view = ChartView(self.chart) self.setCentralWidget(self.chart_view) def setupMenu(self): """Create a simple menu to manage the dock widget.""" menu_bar = self.menuBar() menu_bar.setNativeMenuBar(False) # Create view menu and add actions view_menu = menu_bar.addMenu('View') view_menu.addAction(self.toggle_dock_tools_act) def setupToolsDockWidget(self): """Set up the dock widget that displays different tools and themes for interacting with the chart. Also displays the data values in a table view object.""" tools_dock = QDockWidget() tools_dock.setWindowTitle("Tools") tools_dock.setMinimumWidth(400) tools_dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) # Create widgets for dock widget area themes_cb = QComboBox() themes_cb.addItems(["Light", "Cerulean Blue", "Dark", "Sand Brown", "NCS Blue", "High Contrast", "Icy Blue", "Qt"]) themes_cb.currentTextChanged.connect(self.changeChartTheme) self.animations_cb = QComboBox() self.animations_cb.addItem("No Animation", QChart.NoAnimation) self.animations_cb.addItem("Grid Animation", QChart.GridAxisAnimations) self.animations_cb.addItem("Series Animation", QChart.SeriesAnimations) self.animations_cb.addItem("All Animations", QChart.AllAnimations) self.animations_cb.currentIndexChanged.connect(self.changeAnimations) self.legend_cb = QComboBox() self.legend_cb.addItem("No Legend") self.legend_cb.addItem("Align Left", Qt.AlignLeft) self.legend_cb.addItem("Align Top", Qt.AlignTop) self.legend_cb.addItem("Align Right", Qt.AlignRight) self.legend_cb.addItem("Align Bottom", Qt.AlignBottom) self.legend_cb.currentTextChanged.connect(self.changeLegend) self.antialiasing_check_box = QCheckBox() self.antialiasing_check_box.toggled.connect(self.toggleAntialiasing) reset_button = QPushButton("Reset Chart Axes") reset_button.clicked.connect(self.resetChartZoom) # Create table view and set its model data_table_view = QTableView() data_table_view.setModel(self.model) data_table_view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) data_table_view.verticalHeader().setSectionResizeMode(QHeaderView.Stretch) dock_form = QFormLayout() dock_form.setAlignment(Qt.AlignTop) dock_form.addRow("Themes:", themes_cb) dock_form.addRow("Animations:", self.animations_cb) dock_form.addRow("Legend:", self.legend_cb) dock_form.addRow("Anti-Aliasing", self.antialiasing_check_box) dock_form.addRow(reset_button) dock_form.addRow(data_table_view) # Create QWidget object to act as a container for dock widgets tools_container = QWidget() tools_container.setLayout(dock_form) tools_dock.setWidget(tools_container) self.addDockWidget(Qt.LeftDockWidgetArea, tools_dock) # Handles the visibility of the dock widget self.toggle_dock_tools_act = tools_dock.toggleViewAction() def changeChartTheme(self, text): """Slot for changing the theme of the chart.""" themes_dict = {"Light": 0, "Cerulean Blue": 1, "Dark": 2, "Sand Brown": 3, "NCS Blue": 4, "High Contrast": 5, "Icy Blue": 6, "Qt": 7} theme = themes_dict.get(text) if theme == 0: self.setupChart() else: self.chart.setTheme(theme) def changeAnimations(self): """Slot for changing the animation style of the chart.""" animation = QChart.AnimationOptions( self.animations_cb.itemData(self.animations_cb.currentIndex())) self.chart.setAnimationOptions(animation) def changeLegend(self, text): """Slot for turning off the legend, or changing its location.""" alignment = self.legend_cb.itemData(self.legend_cb.currentIndex()) if text == "No Legend": self.chart.legend().hide() else: self.chart.legend().setAlignment(Qt.Alignment(alignment)) self.chart.legend().show() def toggleAntialiasing(self, state): """If self.antialiasing_check_box.isChecked() is True, turn on antialiasing.""" if state: self.chart_view.setRenderHint(QPainter.Antialiasing, on=True) else: self.chart_view.setRenderHint(QPainter.Antialiasing, on=False) def resetChartZoom(self): """Reset the chart and the axes.""" self.chart.zoomReset() self.axis_x.setRange(1880, 2016) self.axis_y.setRange(0, 40) def loadCSVFile(self): """Load data from CSV file for the chart. Select and store x and y values and labels into Python list objects. Return the xy_data_and_labels list.""" file_name = "files/social_spending_simplified.csv" with open(file_name, "r") as csv_f: reader = csv.reader(csv_f) header_labels = next(reader) row_values = [] # Store current row values xy_data_and_labels = [] # Store all values for i, row in enumerate(reader): x = int(row[2]) y = float(row[3]) label = row[0] row_values.append(x) row_values.append(y) row_values.append(label) # Add row_values to xy_data_and_labels, then reset row_values xy_data_and_labels.append(row_values) row_values = [] return xy_data_and_labels
class window(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) try: self.maxVal = float(list(data.values())[0]) if self.maxVal * 60 < 1: self.set0 = QBarSet('Seconds') self.set0.append( [round(float(x) * 60 * 60, 1) for x in data.values()]) self.maxVal = round(self.maxVal * 60 * 60, 1) elif self.maxVal < 1: self.set0 = QBarSet('Minutes') self.set0.append( [round(float(x) * 60, 1) for x in data.values()]) self.maxVal = round(self.maxVal * 60, 1) else: self.set0 = QBarSet('Hours') self.set0.append([round(float(x), 1) for x in data.values()]) self.maxVal = round(self.maxVal, 1) except: self.set0 = QBarSet('NotEnoughData') self.series = QBarSeries() self.series.append(self.set0) self.chart = QChart() self.chart.setTheme(QChart.ChartThemeHighContrast) self.chart.addSeries(self.series) self.chart.setTitle(header) self.chart.setAnimationOptions(QChart.SeriesAnimations) months = (data.keys()) self.axisX = QBarCategoryAxis() self.axisX.append(months) self.axisY = QValueAxis() try: self.axisY.setRange(0, self.maxVal) if self.maxVal > 19: self.axisY.setTickCount(15) elif self.maxVal > 10: self.axisY.setTickCount(10) else: self.axisY.setTickCount(5) #axisY.setTickInterval(1) #axisY.applyNiceNumbers() except: self.chart.setTitle("No Data") self.chart.addAxis(self.axisX, Qt.AlignBottom) self.chart.addAxis(self.axisY, Qt.AlignLeft) self.chart.legend().setVisible(True) self.chart.legend().setAlignment(Qt.AlignBottom) self.chartView = QChartView(self.chart) self.vert_l = QVBoxLayout() self.vert_l.addWidget(self.chartView) self.setLayout(self.vert_l)
class QmyMainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) #调用父类构造函数,创建窗体 self.ui=Ui_MainWindow() #创建UI对象 self.ui.setupUi(self) #构造UI界面 self.setWindowTitle("Demo12_7, QAreaSeries绘制填充图") self.__buildStatusBar() self.ui.chartView.setRenderHint(QPainter.Antialiasing) self.ui.chartView.setCursor(Qt.CrossCursor) #设置鼠标指针为十字星 self.ui.chartView.mouseMove.connect(self.do_chartView_mouseMove) self.__colorLine=Qt.darkBlue #曲线颜色,darkBlue self.__colorFill=Qt.darkBlue #填充颜色 gray self.__iniChart() #创建self.chart ## "填充类型"4个RadioButton关联槽函数 self.ui.radioFill_Pos.clicked.connect(self.do_redrawFill) #positive self.ui.radioFill_Neg.clicked.connect(self.do_redrawFill) #negative self.ui.radioFill_Both.clicked.connect(self.do_redrawFill) #both self.ui.radioFill_None.clicked.connect(self.do_redrawWave) #wiggle ## ==============自定义功能函数======================== def __buildStatusBar(self): self.__labFileName = QLabel("数据文件") self.__labFileName.setMinimumWidth(200) self.ui.statusBar.addWidget(self.__labFileName) self.__labChartXY = QLabel("Chart, X=, Y=") self.__labChartXY.setMinimumWidth(200) self.ui.statusBar.addWidget(self.__labChartXY) self.__labAreaXY = QLabel("AreaSeries,X=, Y=") self.__labAreaXY.setMinimumWidth(200) self.ui.statusBar.addWidget(self.__labAreaXY) def __iniChart(self): self.chart = QChart() #创建 chart self.chart.setTitle("地震波形") self.chart.legend().setVisible(False) #不显示图例 self.ui.chartView.setChart(self.chart) #chart添加到chartView ## 创建坐标轴X self.__axisX = QValueAxis() # bottom 轴是 QValueAxis self.__axisX.setTitleText("时间(秒)") self.__axisX.setRange(0, 10) self.__axisX.setTickCount(10) self.__axisX.setLabelFormat("%.2f") #标签格式 self.chart.addAxis(self.__axisX,Qt.AlignBottom) ## 创建坐标轴Y self.__axisY = QValueAxis() # left 轴是 QValueAxis self.__axisY.setTitleText("幅度") self.__axisY.setRange(-5,5) self.__axisY.setTickCount(5) self.__axisY.setLabelFormat("%.2f") #标签格式 self.chart.addAxis(self.__axisY,Qt.AlignLeft) ## ==============event处理函数========================== ## ==========由connectSlotsByName()自动连接的槽函数============ ##=====工具栏 按钮功能 @pyqtSlot() ##“打开文件”按钮 def on_actOpen_triggered(self): curPath=QDir.currentPath() #获取当前路径 filename,flt=QFileDialog.getOpenFileName(self,"打开一个文件",curPath, "地震数据文件(*.txt);;所有文件(*.*)") if (filename==""): return aFile=open(filename,'r') allLines=aFile.readlines() #读取所有行,list类型,每行末尾带有 \n aFile.close() fileInfo=QFileInfo(filename) QDir.setCurrent(fileInfo.absolutePath()) self.__labFileName.setText("数据文件:"+fileInfo.fileName()) rowCnt=len(allLines) #行数,即数据点数 self.__vectData=[0]*rowCnt #列表 for i in range(rowCnt): lineText=allLines[i].strip() #字符串表示的数字 self.__vectData[i]=float(lineText) minV=min(self.__vectData) #最小值 self.ui.spinY_Min.setValue(minV) maxV=max(self.__vectData) #最大值 self.ui.spinY_Max.setValue(maxV) if self.ui.radioFill_None.isChecked(): self.do_redrawWave() #绘制波形曲线 else: self.do_redrawFill() #绘制有填充的波形 self.ui.frameSetup.setEnabled(True) @pyqtSlot() def on_actZoomIn_triggered(self): self.ui.chartView.chart().zoom(1.2) @pyqtSlot() def on_actZoomOut_triggered(self): self.ui.chartView.chart().zoom(0.8) @pyqtSlot() def on_actZoomReset_triggered(self): self.ui.chartView.chart().zoomReset() ## Y轴设置 @pyqtSlot() ##设置坐标范围 def on_btnY_SetRange_clicked(self): self.__axisY.setRange(self.ui.spinY_Min.value(), self.ui.spinY_Max.value()) @pyqtSlot(int) ##分度数 def on_spinY_Ticks_valueChanged(self,arg1): self.__axisY.setTickCount(arg1) @pyqtSlot(bool) ##显示网格线 def on_chkBoxY_GridLine_clicked(self,checked): self.__axisY.setGridLineVisible(checked) ## X轴设置 @pyqtSlot() ##设置坐标范围 def on_btnX_SetRange_clicked(self): self.__axisX.setRange(self.ui.spinX_Min.value(), self.ui.spinX_Max.value()) @pyqtSlot(int) ##分度数 def on_spinX_Ticks_valueChanged(self,arg1): self.__axisX.setTickCount(arg1) @pyqtSlot(bool) ##显示网格线 def on_chkBoxX_GridLine_clicked(self,checked): self.__axisX.setGridLineVisible(checked) ## =============自定义槽函数=============================== @pyqtSlot() ##绘制原始波形曲线 def do_redrawWave(self): self.chart.removeAllSeries() # 删除所有序列 pen=QPen(self.__colorLine) # 曲线颜色 pen.setWidth(2) seriesWave = QLineSeries() seriesWave.setUseOpenGL(True) seriesWave.setPen(pen) vx=0 intv=0.001 #1000Hz采样 pointCount=len(self.__vectData) for i in range(pointCount): value=self.__vectData[i] seriesWave.append(vx,value) vx =vx+ intv self.__axisX.setRange(0,vx) self.chart.addSeries(seriesWave) seriesWave.attachAxis(self.__axisX) seriesWave.attachAxis(self.__axisY) @pyqtSlot() ##绘制3种填充曲线 def do_redrawFill(self): self.chart.removeAllSeries() #删除所有序列 pen=QPen(self.__colorLine) #线条颜色 pen.setWidth(2) seriesFullWave = QLineSeries() #全波形 seriesFullWave.setUseOpenGL(True) seriesFullWave.setPen(pen) seriesPositive = QLineSeries() #正半部分曲线 seriesPositive.setUseOpenGL(True) seriesPositive.setVisible(False) #不显示 seriesNegative = QLineSeries() #负半部分曲线 seriesNegative.setUseOpenGL(True) seriesNegative.setVisible(False) #不显示即可 seriesZero = QLineSeries() #零均值线 seriesZero.setUseOpenGL(True) seriesZero.setVisible(False) #不显示即可 ## 填充数据 vx=0 intv=0.001 #1000Hz采样,数据点间隔时间 pointCount=len(self.__vectData) for i in range(pointCount): value=self.__vectData[i] seriesFullWave.append(vx,value) #完整波形 seriesZero.append(vx,0) #零值线 if value>0: seriesPositive.append(vx,value) #正半部分波形 seriesNegative.append(vx,0) else: seriesPositive.append(vx,0) seriesNegative.append(vx,value) #负半部分波形 vx =vx+intv self.__axisX.setRange(0,vx) ## 创建QAreaSeries序列,设置上、下界的QLineSeries对象 pen.setStyle(Qt.NoPen) #无线条,隐藏填充区域的边线 if self.ui.radioFill_Pos.isChecked(): #positive fill series = QAreaSeries(seriesPositive, seriesZero) #QAreaSeries series.setColor(self.__colorFill) #填充色 series.setPen(pen) #不显示线条 self.chart.addSeries(series) series.attachAxis(self.__axisX) series.attachAxis(self.__axisY) elif self.ui.radioFill_Neg.isChecked(): #negative fill series = QAreaSeries(seriesZero,seriesNegative) series.setColor(self.__colorFill) series.setPen(pen) #不显示线条 self.chart.addSeries(series) series.attachAxis(self.__axisX) series.attachAxis(self.__axisY) elif self.ui.radioFill_Both.isChecked(): #both fill series = QAreaSeries(seriesZero,seriesFullWave) series.setColor(self.__colorFill) series.setPen(pen) #不显示线条 self.chart.addSeries(series) series.attachAxis(self.__axisX) series.attachAxis(self.__axisY) series.clicked.connect(self.do_area_clicked) #关联槽函数 ## 构建QAreaSeries的两个QLineSeries序列必须添加到chart里,否则程序崩溃 self.chart.addSeries(seriesZero) #隐藏 self.chart.addSeries(seriesPositive) #隐藏 self.chart.addSeries(seriesNegative) #隐藏 self.chart.addSeries(seriesFullWave) #全波形曲线,显示 seriesPositive.attachAxis(self.__axisX) seriesPositive.attachAxis(self.__axisY) seriesNegative.attachAxis(self.__axisX) seriesNegative.attachAxis(self.__axisY) seriesZero.attachAxis(self.__axisX) seriesZero.attachAxis(self.__axisY) seriesFullWave.attachAxis(self.__axisX) seriesFullWave.attachAxis(self.__axisY) def do_chartView_mouseMove(self,point): pt=self.ui.chartView.chart().mapToValue(point) #QPointF 转换为图表的数值 self.__labChartXY.setText("Chart X=%.2f,Y=%.2f"%(pt.x(),pt.y())) #状态栏显示 def do_area_clicked(self,point): self.__labAreaXY.setText("AreaSeries X=%.2f,Y=%.2f" %(point.x(),point.y())) #状态栏显示
def agg_results(self) -> None: """ Display results in the corresponding chart view. :return: nothing :rtype: None """ # aggregate "other" abundances if self.cbAggResults.isChecked(): agg_abundance = ( self.results.iloc[self.sbAggResults.value():].sum()) agg_abundance["glycoform"] = self.tr("other") self.results_agg = ( self.results.iloc[:self.sbAggResults.value()].append( agg_abundance, ignore_index=True)) else: self.results_agg = self.results # extract x- and y-values from series x_values = list(self.results_agg["glycoform"].str.split(" or").str[0]) y_values_obs = list(self.results_agg["abundance"]) y_values_cor = list(self.results_agg["corr_abundance"]) # assemble the chart bar_set_obs = QBarSet(self.tr("observed")) bar_set_obs.append(y_values_obs) bar_set_obs.setColor(QColor("#225ea8")) bar_set_obs.hovered.connect(self.update_results_label) bar_set_cor = QBarSet(self.tr("corrected")) bar_set_cor.append(y_values_cor) bar_set_cor.setColor(QColor("#41b6c4")) bar_set_cor.hovered.connect(self.update_results_label) bar_series = QBarSeries() bar_series.append([bar_set_obs, bar_set_cor]) x_axis = QBarCategoryAxis() x_axis.append(x_values) x_axis.setTitleVisible(False) x_axis.setLabelsAngle(270) range_min = min( self.results_agg[["abundance", "corr_abundance"]].min().min(), 0) range_min = math.floor(range_min / 20) * 20 range_max = (self.results_agg[["abundance", "corr_abundance"]].max().max()) range_max = math.ceil(range_max / 20) * 20 tick_count = (range_max - range_min) // 20 + 1 y_axis = QValueAxis() y_axis.setRange(range_min, range_max) y_axis.setTickCount(tick_count) y_axis.setTitleText(self.tr("abundance")) y_axis.setLabelFormat("%d") chart = QChart() chart.addSeries(bar_series) chart.setAxisX(x_axis, bar_series) chart.setAxisY(y_axis, bar_series) chart.legend().setVisible(False) chart.setBackgroundRoundness(0) chart.layout().setContentsMargins(0, 0, 0, 0) chart.setMargins(QMargins(5, 5, 5, 5)) self.cvResults.setChart(chart)
class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self, weight_path, out_file_path, parent=None): super(MainWindow, self).__init__(parent) self.setupUi(self) self.setWindowTitle("VAT ROLL COMPARE LABEL TOOL" + " " + CODE_VER) self.showMaximized() '''按键绑定''' # 输入媒体 self.import_media_pushButton.clicked.connect(self.import_media) # 导入 self.start_predict_pushButton.clicked.connect( self.predict_button_click) # 开始推理 # 输出媒体 self.open_predict_file_pushButton.clicked.connect( self.open_file_in_browser) # 文件中显示推理视频 # 下方 self.play_pushButton.clicked.connect( self.play_pause_button_click) # 播放 self.pause_pushButton.clicked.connect( self.play_pause_button_click) # 暂停 self.button_dict = dict() self.button_dict.update({ "import_media_pushButton": self.import_media_pushButton, "start_predict_pushButton": self.start_predict_pushButton, "open_predict_file_pushButton": self.open_predict_file_pushButton, "play_pushButton": self.play_pushButton, "pause_pushButton": self.pause_pushButton, }) '''媒体流绑定输出''' self.input_player = QMediaPlayer() # 媒体输入的widget self.input_player.setVideoOutput(self.input_video_widget) self.input_player.positionChanged.connect( self.change_slide_bar) # 播放进度条 self.output_player = QMediaPlayer() # 媒体输出的widget self.output_player.setVideoOutput(self.output_video_widget) '''初始化GPU chart''' self.series = QSplineSeries() self.chart_init() '''初始化GPU定时查询定时器''' # 使用QTimer,0.5秒触发一次,更新数据 self.timer = QTimer(self) self.timer.timeout.connect(self.draw_gpu_info_chart) self.timer.start(500) # 播放时长, 以 input 的时长为准 self.video_length = 0 self.out_file_path = out_file_path # 推理使用另外一线程 self.predict_handler_thread = PredictHandlerThread( self.output_player, self.out_file_path, weight_path, self.predict_info_plainTextEdit, self.predict_progressBar, self.fps_label, self.button_dict) # 界面美化 self.gen_better_gui() def gen_better_gui(self): """ 美化界面 :return: """ # Play 按钮 play_icon = QIcon() play_icon.addPixmap(QPixmap("./UI/icon/play.png"), QIcon.Normal, QIcon.Off) self.play_pushButton.setIcon(play_icon) # Pause 按钮 play_icon = QIcon() play_icon.addPixmap(QPixmap("./UI/icon/pause.png"), QIcon.Normal, QIcon.Off) self.pause_pushButton.setIcon(play_icon) def chart_init(self): """ 初始化 GPU 折线图 :return: """ # self.gpu_info_chart._chart = QChart(title="折线图堆叠") # 创建折线视图 self.gpu_info_chart._chart = QChart() # 创建折线视图 # chart._chart.setBackgroundVisible(visible=False) # 背景色透明 self.gpu_info_chart._chart.setBackgroundBrush(QBrush( QColor("#FFFFFF"))) # 改变图背景色 # 设置曲线名称 self.series.setName("GPU Utilization") # 把曲线添加到QChart的实例中 self.gpu_info_chart._chart.addSeries(self.series) # 声明并初始化X轴,Y轴 self.dtaxisX = QDateTimeAxis() self.vlaxisY = QValueAxis() # 设置坐标轴显示范围 self.dtaxisX.setMin(QDateTime.currentDateTime().addSecs(-300 * 1)) self.dtaxisX.setMax(QDateTime.currentDateTime().addSecs(0)) self.vlaxisY.setMin(0) self.vlaxisY.setMax(100) # 设置X轴时间样式 self.dtaxisX.setFormat("hh:mm:ss") # 设置坐标轴上的格点 self.dtaxisX.setTickCount(5) self.vlaxisY.setTickCount(10) # 设置坐标轴名称 self.dtaxisX.setTitleText("Time") self.vlaxisY.setTitleText("Percent") # 设置网格不显示 self.vlaxisY.setGridLineVisible(False) # 把坐标轴添加到chart中 self.gpu_info_chart._chart.addAxis(self.dtaxisX, Qt.AlignBottom) self.gpu_info_chart._chart.addAxis(self.vlaxisY, Qt.AlignLeft) # 把曲线关联到坐标轴 self.series.attachAxis(self.dtaxisX) self.series.attachAxis(self.vlaxisY) # 生成 折线图 self.gpu_info_chart.setChart(self.gpu_info_chart._chart) def draw_gpu_info_chart(self): """ 绘制 GPU 折线图 :return: """ # 获取当前时间 time_current = QDateTime.currentDateTime() # 更新X轴坐标 self.dtaxisX.setMin(QDateTime.currentDateTime().addSecs(-300 * 1)) self.dtaxisX.setMax(QDateTime.currentDateTime().addSecs(0)) # 当曲线上的点超出X轴的范围时,移除最早的点 remove_count = 600 if self.series.count() > remove_count: self.series.removePoints(0, self.series.count() - remove_count) # 对 y 赋值 # yint = random.randint(0, 100) gpu_info = get_gpu_info() yint = gpu_info[0].get("gpu_load") # 添加数据到曲线末端 self.series.append(time_current.toMSecsSinceEpoch(), yint) def import_media(self): """ 导入媒体文件 :return: """ self.parameter_source = QFileDialog.getOpenFileUrl()[0] self.input_player.setMedia(QMediaContent( self.parameter_source)) # 选取视频文件 # 设置 output 为一张图片,防止资源被占用 path_current = str(Path.cwd().joinpath("area_dangerous\1.jpg")) self.output_player.setMedia( QMediaContent(QUrl.fromLocalFile(path_current))) # 将 QUrl 路径转为 本地路径str self.predict_handler_thread.parameter_source = self.parameter_source.toLocalFile( ) self.input_player.pause() # 显示媒体 image_flag = os.path.splitext( self.predict_handler_thread.parameter_source)[-1].lower( ) in img_formats for item, button in self.button_dict.items(): if image_flag and item in ['play_pushButton', 'pause_pushButton']: button.setEnabled(False) else: button.setEnabled(True) # self.output_player.setMedia(QMediaContent(QFileDialog.getOpenFileUrl()[0])) # 选取视频文件 def predict_button_click(self): """ 推理按钮 :return: """ # 启动线程去调用 self.predict_handler_thread.start() def change_slide_bar(self, position): """ 进度条移动 :param position: :return: """ self.video_length = self.input_player.duration() + 0.1 self.video_horizontalSlider.setValue( round((position / self.video_length) * 100)) self.video_percent_label.setText( str(round((position / self.video_length) * 100, 2)) + '%') @pyqtSlot() def play_pause_button_click(self): """ 播放、暂停按钮回调事件 :return: """ name = self.sender().objectName() if self.parameter_source == "": return if name == "play_pushButton": print("play") self.input_player.play() self.output_player.play() elif name == "pause_pushButton": self.input_player.pause() self.output_player.pause() @pyqtSlot() def open_file_in_browser(self): os.system(f"start explorer {self.out_file_path}") @pyqtSlot() def closeEvent(self, *args, **kwargs): """ 重写关闭事件 :param args: :param kwargs: :return: """ print("Close")
class QmyMainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) #调用父类构造函数,创建窗体 self.ui = Ui_MainWindow() #创建UI对象 self.ui.setupUi(self) #构造UI界面 self.setWindowTitle("Demo12_4, 对数坐标轴和多坐标轴") self.__buildStatusBar() self.ui.frameSetup.setEnabled(False) #禁用控制面板 ## 创建QmyChartView对象,并添加到窗口上 self.ui.chartView.setRenderHint(QPainter.Antialiasing) self.ui.chartView.setCursor(Qt.CrossCursor) #设置鼠标指针为十字星 self.__iniChart() # 创建self.chart ## ==============自定义功能函数======================== def __buildStatusBar(self): ##构建状态栏 self.__labMagXY = QLabel("幅频曲线,") self.__labMagXY.setMinimumWidth(250) self.ui.statusBar.addWidget(self.__labMagXY) self.__labPhaseXY = QLabel("相频曲线,") self.__labPhaseXY.setMinimumWidth(250) self.ui.statusBar.addWidget(self.__labPhaseXY) def __iniChart(self): ##图表初始化 self.chart = QChart() #创建 chart self.chart.setTitle("二阶系统频率特性") self.chart.legend().setVisible(True) self.ui.chartView.setChart(self.chart) #chart添加到chartView ##2. 创建坐标轴 ## bottom 轴是 QLogValueAxis self.__axisFreq = QLogValueAxis() self.__axisFreq.setLabelFormat("%.1f") #标签格式 self.__axisFreq.setTitleText("角频率(rad/sec)") self.__axisFreq.setRange(0.1, 100) self.__axisFreq.setMinorTickCount(9) self.chart.addAxis(self.__axisFreq, Qt.AlignBottom) ## left 轴是 QValueAxis self.__axisMag = QValueAxis() self.__axisMag.setTitleText("幅度(dB)") self.__axisMag.setRange(-40, 10) self.__axisMag.setTickCount(6) self.__axisMag.setLabelFormat("%.1f") #标签格式 self.chart.addAxis(self.__axisMag, Qt.AlignLeft) ## right 轴是 QValueAxis self.__axisPhase = QValueAxis() self.__axisPhase.setTitleText("相位(度)") self.__axisPhase.setRange(-200, 0) self.__axisPhase.setTickCount(6) self.__axisPhase.setLabelFormat("%.0f") #标签格式 self.chart.addAxis(self.__axisPhase, Qt.AlignRight) def __loadData(self, allLines): ##从字符串列表读取数据 rowCnt = len(allLines) #文本行数 self.__vectW = [0] * rowCnt self.__vectMag = [0] * rowCnt self.__VectPhase = [0] * rowCnt for i in range(rowCnt): lineText = allLines[i].strip() #一行的文字,必须去掉末尾的\n strList = lineText.split() #分割为字符串列表 self.__vectW[i] = float(strList[0]) #频率 self.__vectMag[i] = float(strList[1]) #幅度 self.__VectPhase[i] = float(strList[2]) #相位 def __drawBode(self): self.chart.removeAllSeries() #删除所有序列 ## 创建序列 pen = QPen(Qt.red) pen.setWidth(2) seriesMag = QLineSeries() #幅频曲线序列 seriesMag.setName("幅频曲线") seriesMag.setPen(pen) seriesMag.setPointsVisible(False) seriesMag.hovered.connect(self.do_seriesMag_hovered) seriesPhase = QLineSeries() #相频曲线序列 pen.setColor(Qt.blue) seriesPhase.setName("相频曲线") seriesPhase.setPen(pen) seriesPhase.setPointsVisible(True) seriesPhase.hovered.connect(self.do_seriesPhase_hovered) ## 为序列添加数据点 count = len(self.__vectW) #数据点数 for i in range(count): seriesMag.append(self.__vectW[i], self.__vectMag[i]) seriesPhase.append(self.__vectW[i], self.__VectPhase[i]) ##设置坐标轴范围 minMag = min(self.__vectMag) maxMag = max(self.__vectMag) minPh = min(self.__VectPhase) maxPh = max(self.__VectPhase) self.__axisMag.setRange(minMag, maxMag) self.__axisPhase.setRange(minPh, maxPh) ##序列添加到chart,并指定坐标轴 self.chart.addSeries(seriesMag) seriesMag.attachAxis(self.__axisFreq) seriesMag.attachAxis(self.__axisMag) self.chart.addSeries(seriesPhase) seriesPhase.attachAxis(self.__axisFreq) seriesPhase.attachAxis(self.__axisPhase) for marker in self.chart.legend().markers(): #QLegendMarker类型列表 marker.clicked.connect(self.do_LegendMarkerClicked) ## ==============event处理函数========================== ## ==========由connectSlotsByName()自动连接的槽函数============ @pyqtSlot() ##打开数据 def on_actOpen_triggered(self): curPath = QDir.currentPath() #获取当前路径 filename, flt = QFileDialog.getOpenFileName( self, "打开一个文件", curPath, "频率响应数据文件(*.txt);;所有文件(*.*)") if (filename == ""): return aFile = open(filename, 'r') allLines = aFile.readlines() #读取所有行,list类型,每行末尾带有 \n aFile.close() fileInfo = QFileInfo(filename) QDir.setCurrent(fileInfo.absolutePath()) self.__loadData(allLines) #解析数据 self.__drawBode() #绘制幅频曲线和相频曲线 self.ui.frameSetup.setEnabled(True) @pyqtSlot() ##放大 def on_actZoomIn_triggered(self): self.ui.chartView.chart().zoom(1.2) @pyqtSlot() ##缩小 def on_actZoomOut_triggered(self): self.ui.chartView.chart().zoom(0.8) @pyqtSlot() ##原始大小 def on_actZoomReset_triggered(self): self.ui.chartView.chart().zoomReset() ##图表外观控制 @pyqtSlot(int) ##主题 def on_comboTheme_currentIndexChanged(self, index): self.ui.chartView.chart().setTheme(QChart.ChartTheme(index)) @pyqtSlot(bool) ##显示图例 def on_chkBox_Legend_clicked(self, checked): self.ui.chartView.chart().legend().setVisible(checked) ## 幅频曲线设置 @pyqtSlot() ##设置坐标范围 def on_btnMag_SetRange_clicked(self): self.__axisMag.setRange(self.ui.spinMag_Min.value(), self.ui.spinMag_Max.value()) @pyqtSlot(int) ##分度数 def on_spinMag_Ticks_valueChanged(self, arg1): self.__axisMag.setTickCount(arg1) @pyqtSlot(bool) ##显示数据点 def on_chkBoxMag_Point_clicked(self, checked): seriesMag = self.chart.series()[0] seriesMag.setPointsVisible(checked) ## 相频曲线设置 @pyqtSlot() ##设置坐标范围 def on_btnPh_SetRange_clicked(self): self.__axisPhase.setRange(self.ui.spinPh_Min.value(), self.ui.spinPh_Max.value()) @pyqtSlot(int) ##分度数 def on_spinPh_Ticks_valueChanged(self, arg1): self.__axisPhase.setTickCount(arg1) @pyqtSlot(bool) ##显示数据点 def on_chkBoxPh_Point_clicked(self, checked): seriesPhase = self.chart.series()[1] seriesPhase.setPointsVisible(checked) ## 频率坐标轴 @pyqtSlot() ##设置坐标范围 def on_btnX_SetRange_clicked(self): self.__axisFreq.setRange(self.ui.spinX_Min.value(), self.ui.spinX_Max.value()) @pyqtSlot(int) ##次分度数 def on_spinX_MinorTicks_valueChanged(self, arg1): self.__axisFreq.setMinorTickCount(arg1) ## =============自定义槽函数=============================== def do_LegendMarkerClicked(self): marker = self.sender() #QLegendMarker if (marker.type() != QLegendMarker.LegendMarkerTypeXY): return marker.series().setVisible(not marker.series().isVisible()) marker.setVisible(True) alpha = 1.0 if not marker.series().isVisible(): alpha = 0.5 brush = marker.labelBrush() #QBrush color = brush.color() #QColor color.setAlphaF(alpha) brush.setColor(color) marker.setLabelBrush(brush) brush = marker.brush() color = brush.color() color.setAlphaF(alpha) brush.setColor(color) marker.setBrush(brush) pen = marker.pen() #QPen color = pen.color() color.setAlphaF(alpha) pen.setColor(color) marker.setPen(pen) def do_seriesMag_hovered(self, point, state): if state: hint = "幅频曲线:频率=%.1f, 幅度=%.1f dB" % (point.x(), point.y()) self.__labMagXY.setText(hint) ## else: ## self.__labMagXY.setText("幅频曲线") def do_seriesPhase_hovered(self, point, state): if state: hint = "相频曲线:频率=%.1f, 相位=%.1f 度" % (point.x(), point.y()) self.__labPhaseXY.setText(hint)
class Chart(QWidget): def __init__(self, ch0Name='ch0', ch1Name='ch1', ch2Name='ch2', ch3Name='ch3'): super(Chart, self).__init__() self.ch0Name = ch0Name self.ch1Name = ch1Name self.ch2Name = ch2Name self.ch3Name = ch3Name self.data = [] self.initUI() def initUI(self): vbox = QVBoxLayout() vbox.addWidget(self.chartUI()) vbox.addWidget(self.controlUI()) self.setLayout(vbox) def chartUI(self): self.chart1 = QLineSeries() self.chart1.setName(self.ch0Name) self.chart1.setPen(QPen(Qt.red)) self.chart2 = QLineSeries() self.chart2.setName(self.ch1Name) self.chart2.setPen(QPen(Qt.darkYellow)) self.chart3 = QLineSeries() self.chart3.setName(self.ch2Name) self.chart3.setPen(QPen(Qt.green)) self.chart4 = QLineSeries() self.chart4.setName(self.ch3Name) self.chart4.setPen(QPen(Qt.blue)) self.chart = QChart() self.chart.addSeries(self.chart1) self.chart.addSeries(self.chart2) self.chart.addSeries(self.chart3) self.chart.addSeries(self.chart4) self.chart.setAnimationOptions(QChart.AllAnimations) self.chart.setTitle("laser data") self.axis_x = QValueAxis() self.axis_y = QValueAxis() self.axis_x.setTickCount(10) self.axis_y.setTickCount(10) self.axis_x.setLabelFormat('%d') self.axis_y.setLabelFormat('%d') self.axis_x.setRange(0, 1000) self.axis_y.setRange(100, 300) self.chart.setAxisX(self.axis_x, self.chart1) self.chart.setAxisY(self.axis_y, self.chart1) self.chart.setAxisX(self.axis_x, self.chart2) self.chart.setAxisY(self.axis_y, self.chart2) self.chart.setAxisX(self.axis_x, self.chart3) self.chart.setAxisY(self.axis_y, self.chart3) self.chart.setAxisX(self.axis_x, self.chart4) self.chart.setAxisY(self.axis_y, self.chart4) self.chartView = QChartView() self.chartView.setChart(self.chart) self.chartView.setRubberBand(QChartView.RectangleRubberBand) self.chartView.setRenderHint(QPainter.Antialiasing) return self.chartView def controlUI(self): self.autoRefreshCb = QCheckBox('自动刷新') self.autoRefreshCb.setChecked(True) self.ch0Enable = QCheckBox(self.ch0Name) self.ch1Enable = QCheckBox(self.ch1Name) self.ch2Enable = QCheckBox(self.ch2Name) self.ch3Enable = QCheckBox(self.ch3Name) self.ch0Enable.setChecked(True) self.ch1Enable.setChecked(True) self.ch2Enable.setChecked(True) self.ch3Enable.setChecked(True) hbox1 = QHBoxLayout() hbox1.addWidget(self.autoRefreshCb) hbox1.addWidget(self.ch0Enable) hbox1.addWidget(self.ch1Enable) hbox1.addWidget(self.ch2Enable) hbox1.addWidget(self.ch3Enable) self.xDataMinLabel = QLabel('x min:') self.xDataMaxLabel = QLabel('x max:') self.yDataMinLabel = QLabel('y min:') self.yDataMaxLabel = QLabel('y max:') self.xDataMinLine = QLineEdit() self.xDataMaxLine = QLineEdit() self.yDataMinLine = QLineEdit() self.yDataMaxLine = QLineEdit() self.setBtn = QPushButton('设置') hbox = QHBoxLayout() hbox.addWidget(self.xDataMinLabel) hbox.addWidget(self.xDataMinLine) hbox.addWidget(self.xDataMaxLabel) hbox.addWidget(self.xDataMaxLine) hbox.addWidget(self.yDataMinLabel) hbox.addWidget(self.yDataMinLine) hbox.addWidget(self.yDataMaxLabel) hbox.addWidget(self.yDataMaxLine) hbox.addWidget(self.setBtn) mainLayout = QVBoxLayout() mainLayout.addLayout(hbox1) mainLayout.addLayout(hbox) frame = QFrame() frame.setLayout(mainLayout) self.setBtn.clicked.connect(self.setAxisRange) self.ch0Enable.clicked.connect(self.changeCh) self.ch1Enable.clicked.connect(self.changeCh) self.ch2Enable.clicked.connect(self.changeCh) self.ch3Enable.clicked.connect(self.changeCh) return frame # @timethis def update(self): x0Data, y0Data, x1Data, y1Data, x2Data, y2Data, x3Data, y3Data = self.data self.chart1.clear() self.chart2.clear() self.chart3.clear() self.chart4.clear() try: for i in range(0, len(x0Data)): if self.ch0Enable.isChecked(): self.chart1.append(QPoint(x0Data[i], y0Data[i])) for i in range(0, len(x1Data)): if self.ch1Enable.isChecked(): self.chart2.append(QPoint(x1Data[i], y1Data[i])) for i in range(0, len(x2Data)): if self.ch2Enable.isChecked(): self.chart3.append(QPoint(x2Data[i], y2Data[i])) for i in range(0, len(x3Data)): if self.ch3Enable.isChecked(): self.chart4.append(QPoint(x3Data[i], y3Data[i])) except: logging.debug('y0Data is %s' % y0Data) logging.debug('y1Data is %s' % y1Data) logging.debug('y2Data is %s' % y2Data) logging.debug('y3Data is %s' % y3Data) self.chart1.clear() self.chart2.clear() self.chart3.clear() self.chart4.clear() # self.chartView.update() if self.autoRefreshCb.isChecked(): self.fillAxisRange() self.setAxisRange() def fillAxisRange(self): x0Data, y0Data, x1Data, y1Data, x2Data, y2Data, x3Data, y3Data = self.data tmp = [min(x0Data), min(x1Data), min(x2Data), min(x3Data)] xDataMin = min(tmp) tmp = [max(x0Data), max(x1Data), max(x2Data), max(x3Data)] xDataMax = max(tmp) tmp = [min(y0Data), min(y1Data), min(y2Data), min(y3Data)] yDataMin = min(tmp) tmp = [max(y0Data), max(y1Data), max(y2Data), max(y3Data)] yDataMax = max(tmp) xDataAvr = (xDataMin + xDataMax) // 2 yDataAvr = (yDataMin + yDataMax) // 2 self.xDataMinLine.setText(str(xDataAvr - xDataAvr*6//5)) self.xDataMaxLine.setText(str(xDataAvr + xDataAvr*6//5)) self.yDataMinLine.setText(str(yDataAvr - yDataAvr*6//5)) self.yDataMaxLine.setText(str(yDataAvr + yDataAvr*6//5)) @pyqtSlot() def setAxisRange(self): if self.xDataMinLine.text() and self.xDataMaxLine.text() and \ self.yDataMinLine.text() and self.yDataMaxLine.text(): self.axis_x.setRange(int(self.xDataMinLine.text()), int(self.xDataMaxLine.text())) self.axis_y.setRange(int(self.yDataMinLine.text()), int(self.yDataMaxLine.text())) else: QMessageBox.warning(self, '警告', '缺少参数') @pyqtSlot() def changeCh(self): self.chart1.clear() self.chart2.clear() self.chart3.clear() self.chart4.clear() x0Data, y0Data, x1Data, y1Data, x2Data, y2Data, x3Data, y3Data = self.data for i in range(0, len(x0Data)): if self.ch0Enable.isChecked(): self.chart1.append(QPoint(x0Data[i], y0Data[i])) for i in range(0, len(x1Data)): if self.ch1Enable.isChecked(): self.chart2.append(QPoint(x1Data[i], y1Data[i])) for i in range(0, len(x2Data)): if self.ch2Enable.isChecked(): self.chart3.append(QPoint(x2Data[i], y2Data[i])) for i in range(0, len(x3Data)): if self.ch3Enable.isChecked(): self.chart4.append(QPoint(x3Data[i], y3Data[i]))