首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

pyqt pyside 随窗口自适应、可缩放、拖动QLabel

操作系统 4.09MB 6 需要积分: 1
立即下载

资源介绍:

pyqt pyside 随窗口自适应、可缩放、拖动QLabel python 在小才玩yolo目标检测时,总是使用PyQt或PySide来展示识别结果。一开始小才使用自带的QLabel来显示图像,但是发现显示的比较呆,原QLabel显示有以下特点: 1. 窗口大小改变时,QLabel图片显示不会跟随窗口变化。 2. 图片不能够缩放,拖动。 于是小才就去搜索学习,许久后,总结加拓展自己实现了一个 随窗口自适应、可缩放、拖动、画框图片的自定义QLabel类(嘲笑请偷偷)。 以上代码是使用的pyside6实现,pyqt和pyside导入的都差不多,如果使用PyQt5的话删除上面pyside6的import,重新使用pycharm的自动导入提示重新import就行。 ImageLabel继承的QLabel。因此使用时直接将写好的label = QLabel(parent)替换为label = ImageLabel(parent)就可以得到升级!方法上的装饰器check_except是为了方便异常捕捉,小才不想因为显示报错而导致页面卡住然后退出。实现请看小才得另一篇文章python 程序运行
import cv2 from PySide6.QtCore import QPoint, Qt, QRect from PySide6.QtCore import Signal from PySide6.QtGui import QPainter, QPixmap, QImage, QMouseEvent, QKeyEvent, QPen, QColor from PySide6.QtWidgets import QLabel from check_except import check_except class ImageLabel(QLabel): clicked_signal = Signal() # clicked_signal = pyqtSignal()# pyqt5 # 当画框完成后向外输出信号 index: 0原图 1 裁剪后的图片 [2-5裁剪范围]2:x1 3:y1 4:width 5:height bbox_down_signal = Signal(list) def __init__(self, parent, scale_flag=True, move_flag=True, is_original=False, draw_bbox_flag=False): super(ImageLabel, self).__init__(parent) ''' @param parent: 父控件 @param scale_flag: 是否可以缩放 @param move_flag: 是否可以移动 @param is_original: 是否为原图 @param draw_bbox_flag: 是否开启画框 ''' self.scaled_img = None # QPixmap self.cv_image = None # draw_bbox_flag=True 时,为cv2原图 self.point = None # 图片位置 self.start_pos = None # 鼠标按下时的位置 self.end_pos = None # 鼠标松开时的位置 self.right_press = False # 右键正在按压 self.left_press = False # 左键正在按压 self.is_original = is_original # 是否为原图显示 self.x_scale = 1 self.y_scale = 1 # 画框起始点 self.bbox_start_point = None # 画框结束点 self.bbox_end_point = None # 是否可以缩放 scale_flag True 可以缩放 self.scale_flag = scale_flag # 是否可以移动 self.move_flag = move_flag # 是否开启画框 self.draw_bbox_flag = draw_bbox_flag @check_except() def clear_image(self): self.set_q_pixmap(QPixmap(None)) @check_except() def to_q_image(self, image): label_size = (self.height(), self.width()) height, width = image.shape[:2] if not self.is_original: n_height = label_size[0] n_width = int((width / height) * label_size[0]) if n_width > label_size[1]: n_width = label_size[1] n_height = int((height / width) * label_size[1]) image = cv2.resize(image, (n_width, n_height)) else: n_height = height n_width = width channels = len(image.shape) if channels == 2: bytes_per_line = n_width q_image = QImage(image.data, n_width, n_height, bytes_per_line, QImage.Format_Grayscale8) else: bytes_per_line = 3 * n_width q_image = QImage(image.data, n_width, n_height, bytes_per_line, QImage.Format_RGB888).rgbSwapped() return q_image @check_except() def set_cv_image(self, img): # 设置cv2读取的图片 self.set_q_image(self.to_q_image(img)) @check_except() def set_q_image(self, img): # 设置QImage图片 self.set_q_pixmap(QPixmap.fromImage(img)) @check_except() def set_q_pixmap(self, q_pixmap): # 设置QPixmap图片 self.scaled_img = q_pixmap if self.point is None: self._reset_scale() self._reset_point() self.update() def _reset_scale(self): if self.scaled_img: self.x_scale = self.width() / self.scaled_img.width() b = self.scaled_img.height() / self.scaled_img.width() n_height = self.width() * b if n_height > self.height(): self.y_scale = self.height() / self.scaled_img.height() self.x_scale = self.y_scale else: self.y_scale = self.x_scale self.reset_bbox() def _reset_point(self): if self.scaled_img: width, height = self.scaled_img.width(), self.scaled_img.height() p1 = 0 p2 = 0 if self.width() > width * self.x_scale: p1 = int((self.width() - width * self.x_scale) / 2) if self.height() > height * self.y_scale: p2 = int((self.height() - height * self.x_scale) / 2) self.point = QPoint(int(p1 / self.x_scale) if self.x_scale != 0 else 0, int(p2 / self.y_scale) if self.y_scale != 0 else 0) # 重置框 self.reset_bbox() def reset_bbox(self): self.bbox_start_point = None self.bbox_end_point = None @check_except() def paintEvent(self, e): if self.scaled_img: painter = QPainter() painter.begin(self) painter.scale(self.x_scale, self.y_scale) painter.drawPixmap(self.point, self.scaled_img) # 此函数中还会用scale对point进行处理 if self.draw_bbox_flag and self.bbox_start_point is not None and self.bbox_end_point is not None: lw = max(round(sum(self.cv_image.shape) / 2 * 0.003), 3) fs = lw / 3 # line width pen = QPen(QColor('red')) pen.setWidth(fs) painter.setPen(pen) painter.drawRect(self.bbox_start_point.x(), self.bbox_start_point.y(), self.bbox_end_point.x() - self.bbox_start_point.x(), self.bbox_end_point.y() - self.bbox_start_point.y()) painter.end() @check_except() def clear_image(self): self.scaled_img = None self.update() @check_except() def wheelEvent(self, event): if self.scale_flag: angle = event.angleDelta() / 8 # 返回QPoint对象,为滚轮转过的数值,单位为1/8度 angleY = angle.y() self.wheel_flag = True # 获取当前鼠标相对于view的位置 if angleY > 0: self.set_scale(x_scale=1.08 * self.x_scale, y_scale=1.08 * self.y_scale) else: # 滚轮下滚 self.set_scale(x_scale=0.92 * self.x_scale, y_scale=0.92 * self.y_scale) if self.x_scale < 0.05: self.x_scale = 0.05 if self.y_scale < 0.05: self.y_scale = 0.05 if self.x_scale > 50: self.x_scale = 50 if self.y_scale > 50: self.y_scale = 50 self.update() def set_scale(self, x_scale=None, y_scale=None): if x_scale is not None: self.x_scale = x_scale if y_scale is not None: self.y_scale = y_scale @check_except() def mouseMoveEvent(self, e): if self.scaled_img is None: return if self.right_press and self.move_flag: self.end_pos: QPoint = e.pos() - self.start_pos # 当前位置-起始位置=差值 x = round(self.end_pos.x() / self.x_scale) y = round(self.end_pos.y() / self.y_scale) self.point = self.point + QPoint(x, y) # 左上角的距离变化 if self.bbox_start_point is not None: self.bbox_end_point = self.bbox_end_point + QPoint(x, y) if self.bbox_start_point is not None: self.bbox_start_point = self.bbox_start_point + QPoint(x, y) self.start_pos = e.pos() self.repaint() elif self.left_press and self.draw_bbox_flag: img_rect = self.get_image_rect() if img_rect is not None: current_press_point = QPoint(int(e.x() / self.x_scale), int(e.y() / self.y_scale)) if img_rect.contains(current_press_point): # 设置框的结束位置点 self.bbox_end_point = current_press_point self.repaint() @check_except() def mo

资源文件列表:

pyqt pyside 随窗口自适应、可缩放、拖动QLabel.zip 大约有7个文件
  1. pyqt pyside 随窗口自适应、可缩放、拖动QLabel/
  2. pyqt pyside 随窗口自适应、可缩放、拖动QLabel/check_except.py 2.16KB
  3. pyqt pyside 随窗口自适应、可缩放、拖动QLabel/custom_label.py 12.7KB
  4. pyqt pyside 随窗口自适应、可缩放、拖动QLabel/img.png 4.08MB
  5. pyqt pyside 随窗口自适应、可缩放、拖动QLabel/test_custom_label.py 1.7KB
  6. pyqt pyside 随窗口自适应、可缩放、拖动QLabel/test_custom_label.ui 3.25KB
  7. pyqt pyside 随窗口自适应、可缩放、拖动QLabel/test_custom_labelUI.py 4.55KB
0评论
提交 加载更多评论
其他资源 基于fpga的温度采集系统工程,max6675驱动源码,可上传到电脑上位机软件绘制温度曲线 fpga代码、和QT控制软件 是工
基于fpga的温度采集系统工程,max6675驱动源码,可上传到电脑上位机软件绘制温度曲线 fpga代码、和QT控制软件 是工程代码
基于fpga的温度采集系统工程,max6675驱动源码,可上传到电脑上位机软件绘制温度曲线 fpga代码、和QT控制软件 是工
非线性悬架,UKF状态估计 软件使用:Matlab Simulink 适用场景:采用模块化建模方法,搭建空气悬架模型,UKF状态
非线性悬架,UKF状态估计 软件使用:Matlab Simulink 适用场景:采用模块化建模方法,搭建空气悬架模型,UKF状态估计模型,可实现悬架动挠度等状态估计。 包含:simulink源码文件,详细建模说明文档,对应参考资料
非线性悬架,UKF状态估计
软件使用:Matlab Simulink
适用场景:采用模块化建模方法,搭建空气悬架模型,UKF状态
西门子SMART200 PLC和and天平称自由口通讯程序 通俗易懂,注释多,自己编写的,实际项目应用的
西门子SMART200 PLC和and天平称自由口通讯程序。 通俗易懂,注释多,自己编写的,实际项目应用的。
西门子SMART200 PLC和and天平称自由口通讯程序 
通俗易懂,注释多,自己编写的,实际项目应用的
MATLAB四旋翼自适应控制仿真simulink simscape,可更换成自己的无人机solidworks模型 有公式手册需
MATLAB四旋翼自适应控制仿真simulink simscape,可更换成自己的无人机solidworks模型 有公式手册需MATLAB2017版本以上
MATLAB四旋翼自适应控制仿真simulink simscape,可更换成自己的无人机solidworks模型 有公式手册需
120吨双级反渗透程序+混床程序,以及阻垢剂、杀菌剂 加药 一键制水,一键反洗,一键正洗,无人值守 西门子S7-200 sm
120吨双级反渗透程序+混床程序,以及阻垢剂、杀菌剂 加药。 一键制水,一键反洗,一键正洗,无人值守。 西门子S7-200 smart编程软件写的程序,程序+画面+电气原理图。 打包送出去,供初学者学习和研究。 程序有注释。
120吨双级反渗透程序+混床程序,以及阻垢剂、杀菌剂 加药 
一键制水,一键反洗,一键正洗,无人值守 
西门子S7-200 sm
MATLAB编程:基于串并联Sagnac环的微波光子滤波器滤波响应频率响应分析
MATLAB编程:基于串并联Sagnac环的微波光子滤波器滤波响应频率响应分析。
MATLAB编程:基于串并联Sagnac环的微波光子滤波器滤波响应频率响应分析
平行泊车和垂直泊车的程序代码,基于MATLAB开发,包含代码和说明文档
平行泊车和垂直泊车的程序代码,基于MATLAB开发,包含代码和说明文档
平行泊车和垂直泊车的程序代码,基于MATLAB开发,包含代码和说明文档
家庭能源管理matlab 采用matlab编制家庭能源管理程序,包括各种家用电器的调度运行策略,程序通用性好
家庭能源管理matlab 采用matlab编制家庭能源管理程序,包括各种家用电器的调度运行策略,程序通用性好。