pyqt4文档阅读(7.3):QSizeF-QPointF-QRectF

本文详述PyQt4中的QSizeF, QPointF和QRectF,包括它们的属性、方法及与整数版本的区别。重点介绍了如何将浮点数转换为整数、获取最小整数包含矩形以及QRect的“bug”在QRectF中如何避免。" 123067202,10657307,Vue.js动态权限管理:按钮显示与操作控制,"['Vue.js', 'typescript', 'javascript']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本系列文章长期更新修改.


QSizeF,QPointF,QRectF是QSize,QPoint,QRect的浮点数版本.

它们几乎全部函数用法都和整数版本是一样的,因此下面只提供函数表和与整数版本不同的函数或属性.


属性:


QSizeF:

Methods

  • __init__ (self)
  • __init__ (self, QSize sz)
  • __init__ (self, float w, float h)
  • __init__ (self, QSizeF other)
  • QSizeF boundedTo (self, QSizeF otherSize)
  • QSizeF expandedTo (self, QSizeF otherSize)
  • float height (self)
  • bool isEmpty (self)
  • bool isNull (self)
  • bool isValid (self)
  • scale (self, QSizeF s, Qt.AspectRatioMode mode)
  • scale (self, float w, float h, Qt.AspectRatioMode mode)
  • setHeight (self, float h)
  • setWidth (self, float w)
  • QSize toSize (self)
  • transpose (self)
  • float width (self)

Special Methods

  • QSizeF __add__ (self, QSizeF s2)
  • QSizeF __div__ (self, float c)
  • bool __eq__ (self, QSizeF s2)
  • QSizeF __iadd__ (self, QSizeF s)
  • QSizeF __idiv__ (self, float c)
  • QSizeF __imul__ (self, float c)
  • QSizeF __isub__ (self, QSizeF s)
  • QSizeF __mul__ (self, QSizeF s)
  • QSizeF __mul__ (self, float c)<
import os import sys import numpy as np from PyQt5.QtWidgets import (QGraphicsView, QGraphicsScene, QGraphicsPixmapItem, QRubberBand, QApplication, QGraphicsPathItem, QMenu) from PyQt5.QtGui import (QPixmap, QImage, QPainter, QPen, QColor, QBrush, QKeyEvent, QTransform, QPainterPath, QCursor, QPolygonF) from PyQt5.QtCore import (Qt, QPoint, QRect, QSize, QEvent, QPointF, QRectF, pyqtSignal, QTimer, QLineF, QVariantAnimation) class ImageCanvas(QGraphicsView): # 信号定义 zoom_changed = pyqtSignal(float) image_changed = pyqtSignal(QImage) mouse_position_changed = pyqtSignal(QPointF, str) selection_changed = pyqtSignal(QRectF) tool_changed = pyqtSignal(int) # 工具枚举 TOOL_SELECT = 0 TOOL_CROP = 1 TOOL_BRUSH = 2 TOOL_SHAPE = 3 TOOL_TEXT = 4 TOOL_ERASER = 5 def __init__(self, parent=None): super().__init__(parent) self.parent_window = parent self.setRenderHint(QPainter.Antialiasing) self.setRenderHint(QPainter.SmoothPixmapTransform) self.setDragMode(QGraphicsView.ScrollHandDrag) self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setResizeAnchor(QGraphicsView.AnchorUnderMouse) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setInteractive(True) self.viewport().setCursor(Qt.CrossCursor) # 创建场景 self.scene = QGraphicsScene(self) self.setScene(self.scene) self.scene.setBackgroundBrush(QBrush(QColor(50, 50, 50))) # 初始化变量 self.zoom_factor = 1.0 self.min_zoom = 0.05 self.max_zoom = 50.0 self.original_image = QImage() self.displayed_image = QImage() self.current_image_item = None self.saved_transforms = None # 工具相关状态 self.rubber_band = QRubberBand(QRubberBand.Rectangle, self.viewport()) self.rubber_band.hide() self.selection_rect = QRectF() self.selection_active = False self.selection_start = QPointF() # 当前工具状态 self.current_tool = self.TOOL_SELECT self.tool_settings = { &#39;brush_size&#39;: 5, &#39;brush_color&#39;: QColor(255, 0, 0, 255), &#39;eraser_size&#39;: 20, &#39;shape_type&#39;: 0, # 0:矩形, 1:圆形, 2:直线 &#39;antialias&#39;: True, &#39;opacity&#39;: 1.0 } # 绘制相关状态 self.drawing_active = False self.drawing_path = None self.drawing_item = None self.drawing_start = QPointF() self.current_layer = 0 self.layers = [] # 初始化默认图层 self.add_new_layer("Background", QColor(255, 255, 255)) # 历史记录快照 self.snapshots = [] self.current_snapshot = -1 # 安装事件过滤器 self.viewport().installEventFilter(self) # 状态提示定时器 self.status_timer = QTimer(self) self.status_timer.setSingleShot(True) self.status_timer.timeout.connect(self._clear_status) # ==================== 图层管理功能 ==================== def add_new_layer(self, name, fill_color=QColor(0, 0, 0, 0)): """添加新图层""" layer = { &#39;name&#39;: name, &#39;visible&#39;: True, &#39;locked&#39;: False, &#39;opacity&#39;: 1.0, &#39;image&#39;: QImage(self.displayed_image.size(), QImage.Format_ARGB32), &#39;item&#39;: None } layer[&#39;image&#39;].fill(fill_color) self.layers.append(layer) self.current_layer = len(self.layers) - 1 self._render_layers() return self.current_layer def remove_layer(self, index): """移除指定图层""" if 0 <= index < len(self.layers): if self.layers[index][&#39;item&#39;]: self.scene.removeItem(self.layers[index][&#39;item&#39;]) del self.layers[index] if index <= self.current_layer: self.current_layer = max(0, self.current_layer - 1) self._render_layers() def set_current_layer(self, index): """设置当前活动图层""" if 0 <= index < len(self.layers): self.current_layer = index return True return False def toggle_layer_visibility(self, index): """切换图层可见性""" if 0 <= index < len(self.layers): self.layers[index][&#39;visible&#39;] = not self.layers[index][&#39;visible&#39;] self._render_layers() def _render_layers(self): """渲染所有可见图层到显示图像""" if not self.layers: return # 创建一个临时图像来合成所有图层 size = self.displayed_image.size() composite = QImage(size, QImage.Format_ARGB32) composite.fill(Qt.transparent) painter = QPainter(composite) for layer in self.layers: if not layer[&#39;visible&#39;]: continue painter.setOpacity(layer[&#39;opacity&#39;]) painter.drawImage(0, 0, layer[&#39;image&#39;]) painter.end() # 更新显示 self.displayed_image = composite self._show_image(composite) # 更新UI self.image_changed.emit(self.displayed_image) # ==================== 图像管理功能 ==================== def set_image(self, image): """设置要显示的图像""" if image.isNull(): self.clear() return self.original_image = image.copy() self.displayed_image = image.copy() self._clear_layers() self.add_new_layer("Background", Qt.white) self.layers[0][&#39;image&#39;] = image.copy() self.reset_view() self.image_changed.emit(self.displayed_image) self.take_snapshot() def update_image(self): """更新显示的图像""" if not self.displayed_image.isNull(): self._show_image(self.displayed_image) self.image_changed.emit(self.displayed_image) def clear(self): """清除画布""" self.scene.clear() self.current_image_item = None self.displayed_image = QImage() self.original_image = QImage() self.zoom_factor = 1.0 self.zoom_changed.emit(self.zoom_factor) self.resetTransform() self._clear_layers() def reset_view(self): """重置视图到初始状态""" if not self.displayed_image.isNull(): self._show_image(self.displayed_image) self.fit_to_view() def get_current_image(self): """获取当前显示的图像""" return self.displayed_image def get_original_image(self): """获取原始未编辑图像""" return self.original_image def get_pixel_at(self, pos): """获取指定位置的像素颜色""" if self.displayed_image.isNull(): return None if not self.current_image_item: return None # 转换到图像坐标 img_pos = self.map_to_image(pos) x = int(img_pos.x()) y = int(img_pos.y()) # 检查边界 if 0 <= x < self.displayed_image.width() and 0 <= y < self.displayed_image.height(): color = QColor(self.displayed_image.pixel(x, y)) return color return None def map_to_image(self, scene_pos): """将场景坐标映射到图像坐标""" if not self.current_image_item: return QPointF() return self.current_image_item.mapFromScene(scene_pos) # ==================== 缩放功能 ==================== def zoom_in(self): """放大图像""" self.set_zoom(self.zoom_factor * 1.2) def zoom_out(self): """缩小图像""" self.set_zoom(self.zoom_factor * 0.8) def fit_to_view(self): """适应窗口大小""" if self.current_image_item: self.fitInView(self.scene.itemsBoundingRect(), Qt.KeepAspectRatio) self._update_zoom_factor() def set_zoom(self, factor): """设置特定缩放级别""" factor = max(self.min_zoom, min(factor, self.max_zoom)) if abs(factor - self.zoom_factor) > 0.01: self.zoom_factor = factor self.resetTransform() self.scale(factor, factor) self.zoom_changed.emit(self.zoom_factor * 100) def _update_zoom_factor(self): """更新缩放因子""" view_rect = self.transform().mapRect(QRectF(0, 0, 1, 1)) self.zoom_factor = 1.0 / view_rect.width() self.zoom_changed.emit(self.zoom_factor * 100) # ==================== 工具控制功能 ==================== def set_tool(self, tool_id): """设置当前工具""" self.current_tool = tool_id self.tool_changed.emit(tool_id) self._update_cursor() def set_tool_setting(self, key, value): """设置工具参数""" if key in self.tool_settings: self.tool_settings[key] = value self._update_cursor() def _update_cursor(self): """根据当前工具更新光标""" if self.current_tool == self.TOOL_SELECT: self.viewport().setCursor(Qt.CrossCursor) elif self.current_tool == self.TOOL_CROP: self.viewport().setCursor(Qt.CrossCursor) elif self.current_tool == self.TOOL_BRUSH: # 创建画笔形状的光标 size = self.tool_settings[&#39;brush_size&#39;] * self.zoom_factor size = max(6, min(int(size), 100)) pixmap = QPixmap(size, size) pixmap.fill(Qt.transparent) painter = QPainter(pixmap) painter.setPen(QPen(Qt.black, 1)) painter.setBrush(QBrush(self.tool_settings[&#39;brush_color&#39;])) painter.drawEllipse(1, 1, size - 2, size - 2) painter.end() self.viewport().setCursor(QCursor(pixmap, size / 2, size / 2)) elif self.current_tool == self.TOOL_ERASER: # 创建橡皮擦形状的光标 size = self.tool_settings[&#39;eraser_size&#39;] * self.zoom_factor size = max(6, min(int(size), 100)) pixmap = QPixmap(size, size) pixmap.fill(Qt.transparent) painter = QPainter(pixmap) painter.setPen(QPen(Qt.black, 1)) painter.setBrush(QBrush(Qt.white)) painter.drawRect(1, 1, size - 2, size - 2) painter.end() self.viewport().setCursor(QCursor(pixmap, size / 2, size / 2)) elif self.current_tool in [self.TOOL_SHAPE, self.TOOL_TEXT]: self.viewport().setCursor(Qt.CrossCursor) # ==================== 历史记录功能 ==================== def take_snapshot(self): """创建当前状态的快照""" # 只保留最近的20个快照 if self.current_snapshot < len(self.snapshots) - 1: self.snapshots = self.snapshots[:self.current_snapshot + 1] # 保存图层状态 snapshot = { &#39;layers&#39;: [], &#39;current_layer&#39;: self.current_layer } for layer in self.layers: snapshot[&#39;layers&#39;].append({ &#39;image&#39;: layer[&#39;image&#39;].copy(), &#39;visible&#39;: layer[&#39;visible&#39;], &#39;opacity&#39;: layer[&#39;opacity&#39;] }) self.snapshots.append(snapshot) self.current_snapshot = len(self.snapshots) - 1 return True def restore_snapshot(self, index=None): """恢复指定快照""" if index is None: index = self.current_snapshot if 0 <= index < len(self.snapshots): snapshot = self.snapshots[index] # 恢复图层状态 self.layers = [] for layer_data in snapshot[&#39;layers&#39;]: self.layers.append({ &#39;image&#39;: layer_data[&#39;image&#39;].copy(), &#39;visible&#39;: layer_data[&#39;visible&#39;], &#39;opacity&#39;: layer_data[&#39;opacity&#39;], &#39;locked&#39;: False, &#39;name&#39;: f"Layer {len(self.layers)}", &#39;item&#39;: None }) self.current_layer = snapshot[&#39;current_layer&#39;] self._render_layers() self.current_snapshot = index return True return False def undo(self): """撤销上一步操作""" if self.current_snapshot > 0: self.restore_snapshot(self.current_snapshot - 1) return True return False def redo(self): """重做上一步操作""" if self.current_snapshot < len(self.snapshots) - 1: self.restore_snapshot(self.current_snapshot + 1) return True return False # ==================== 绘图功能 ==================== def start_drawing(self, scene_pos): """开始绘图操作""" if self.current_tool in [self.TOOL_BRUSH, self.TOOL_ERASER]: self.drawing_active = True self.drawing_start = scene_pos self.drawing_path = QPainterPath() self.drawing_path.moveTo(self.map_to_image(scene_pos)) if self.current_tool == self.TOOL_BRUSH: pen = QPen(self.tool_settings[&#39;brush_color&#39;], self.tool_settings[&#39;brush_size&#39;]) pen.setCapStyle(Qt.RoundCap) pen.setJoinStyle(Qt.RoundJoin) else: # 橡皮擦 pen = QPen(QColor(255, 255, 255, 255), self.tool_settings[&#39;eraser_size&#39;]) pen.setCapStyle(Qt.RoundCap) if self.tool_settings[&#39;antialias&#39;]: pen.setCosmetic(True) self.drawing_item = QGraphicsPathItem() self.drawing_item.setPen(pen) self.drawing_item.setPath(self.drawing_path) self.drawing_item.setOpacity(self.tool_settings[&#39;opacity&#39;]) self.scene.addItem(self.drawing_item) elif self.current_tool == self.TOOL_SHAPE: self.drawing_active = True self.drawing_start = scene_pos self.drawing_item = self._create_shape(scene_pos, scene_pos) if self.drawing_item: self.scene.addItem(self.drawing_item) elif self.current_tool == self.TOOL_TEXT: # 文本输入通过专用方法处理 pass def continue_drawing(self, scene_pos): """继续绘图操作""" if not self.drawing_active: return if self.current_tool in [self.TOOL_BRUSH, self.TOOL_ERASER]: # 添加路径点 new_point = self.map_to_image(scene_pos) self.drawing_path.lineTo(new_point) self.drawing_item.setPath(self.drawing_path) elif self.current_tool == self.TOOL_SHAPE: # 更新形状 if self.drawing_item: self.scene.removeItem(self.drawing_item) self.drawing_item = self._create_shape(self.drawing_start, scene_pos) if self.drawing_item: self.scene.addItem(self.drawing_item) def stop_drawing(self): """完成绘图操作并应用到图层""" if not self.drawing_active: return if self.drawing_item: # 创建绘制到图层的画家 painter = QPainter(self.layers[self.current_layer][&#39;image&#39;]) painter.setRenderHint(QPainter.Antialiasing, self.tool_settings[&#39;antialias&#39;]) painter.setCompositionMode(QPainter.CompositionMode_SourceOver) painter.setOpacity(self.tool_settings[&#39;opacity&#39;]) # 从绘图项获取路径 path = self.drawing_item.path() # 根据工具应用不同绘制 if self.current_tool == self.TOOL_BRUSH: painter.setPen(QPen( self.tool_settings[&#39;brush_color&#39;], self.tool_settings[&#39;brush_size&#39;], Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin )) painter.setBrush(Qt.NoBrush) painter.drawPath(path) elif self.current_tool == self.TOOL_ERASER: # 使用橡皮擦 painter.setCompositionMode(QPainter.CompositionMode_Clear) painter.setPen(QPen( Qt.transparent, self.tool_settings[&#39;eraser_size&#39;], Qt.SolidLine, Qt.RoundCap )) painter.drawPath(path) 这个代码吗给全
最新发布
06-12
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值