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(200) def chart_init(self): self.chart = QChart() self.series = QSplineSeries() #设置曲线名称 self.series.setName("实时数据") #把曲线添加到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("量程") #设置网格不显示 self.vlaxisY.setGridLineVisible(False) #把坐标轴添加到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)
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")