lcy_888 2024-06-28 09:13 采纳率: 50%
浏览 11
已结题

PySide6扩展QLable实现Word一样的图片裁剪框

使用PySide6扩展QLable控件如何实现Word中图片裁剪框一样的效果。

img

可以通过拖动图片四周的8个控制块获取当前图片的真实裁剪区域(考虑为了显示整图可能等比缩放显示)。

  • 写回答

13条回答 默认 最新

  • 杨同学* 2024-06-28 09:23
    关注

    该回答结合ChatGPT4o及杨同学*共同作答, 如有帮助,还请采纳。
    要实现一个类似于Word中图片裁剪框的效果,可以使用PySide6扩展QLabel控件,添加鼠标事件来实现裁剪区域的控制。我们需要在QLabel上绘制8个控制块,通过拖动这些控制块来改变图片的裁剪区域。下面是一个基本的实现方法:

    代码实现

    1. 安装必要的库

      pip install PySide6
      
    2. 实现代码

    import sys
    from PySide6.QtCore import Qt, QRect, QPoint
    from PySide6.QtGui import QPainter, QPen, QPixmap
    from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QWidget, QVBoxLayout, QSizePolicy
    
    class ImageCropLabel(QLabel):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.setScaledContents(True)
            self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
            
            self.image = QPixmap("image.png")
            self.setPixmap(self.image)
            
            self.crop_rect = QRect(50, 50, 200, 150)
            self.dragging = False
            self.dragging_point = None
            self.control_size = 10
            self.setMinimumSize(1, 1)
    
        def paintEvent(self, event):
            super().paintEvent(event)
            painter = QPainter(self)
            painter.setPen(QPen(Qt.red, 2, Qt.SolidLine))
            painter.drawRect(self.crop_rect)
    
            # Draw the control points
            control_points = self.get_control_points()
            for point in control_points:
                painter.fillRect(point.x() - self.control_size // 2, point.y() - self.control_size // 2,
                                 self.control_size, self.control_size, Qt.blue)
            
        def get_control_points(self):
            return [
                self.crop_rect.topLeft(),
                self.crop_rect.topRight(),
                self.crop_rect.bottomLeft(),
                self.crop_rect.bottomRight(),
                self.crop_rect.topLeft() + QPoint(self.crop_rect.width() // 2, 0),
                self.crop_rect.topLeft() + QPoint(0, self.crop_rect.height() // 2),
                self.crop_rect.bottomRight() - QPoint(self.crop_rect.width() // 2, 0),
                self.crop_rect.bottomRight() - QPoint(0, self.crop_rect.height() // 2),
            ]
            
        def mousePressEvent(self, event):
            if event.button() == Qt.LeftButton:
                self.dragging = False
                self.dragging_point = None
                control_points = self.get_control_points()
                for point in control_points:
                    if (point - event.pos()).manhattanLength() < self.control_size:
                        self.dragging_point = point
                        break
                if self.dragging_point is None and self.crop_rect.contains(event.pos()):
                    self.dragging = True
                    self.drag_start_position = event.pos()
            
        def mouseMoveEvent(self, event):
            if self.dragging_point:
                self.update_crop_rect(self.dragging_point, event.pos())
            elif self.dragging:
                delta = event.pos() - self.drag_start_position
                self.crop_rect.translate(delta)
                self.drag_start_position = event.pos()
            self.update()
            
        def update_crop_rect(self, control_point, new_pos):
            index = self.get_control_points().index(control_point)
            if index == 0:  # topLeft
                self.crop_rect.setTopLeft(new_pos)
            elif index == 1:  # topRight
                self.crop_rect.setTopRight(new_pos)
            elif index == 2:  # bottomLeft
                self.crop_rect.setBottomLeft(new_pos)
            elif index == 3:  # bottomRight
                self.crop_rect.setBottomRight(new_pos)
            elif index == 4:  # top center
                self.crop_rect.setTop(new_pos.y())
            elif index == 5:  # left center
                self.crop_rect.setLeft(new_pos.x())
            elif index == 6:  # bottom center
                self.crop_rect.setBottom(new_pos.y())
            elif index == 7:  # right center
                self.crop_rect.setRight(new_pos.x())
        
        def mouseReleaseEvent(self, event):
            self.dragging = False
            self.dragging_point = None
            
    class MainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            self.setWindowTitle("Image Cropper")
            self.setGeometry(100, 100, 800, 600)
    
            self.label = ImageCropLabel()
            self.setCentralWidget(self.label)
    
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    app.exec()
    

    说明

    1. ImageCropLabel 类

      • 继承自 QLabel 并添加了裁剪区域 (crop_rect)。
      • 实现了 paintEvent 方法来绘制裁剪矩形和控制点。
      • 实现了 mousePressEventmouseMoveEventmouseReleaseEvent 方法来处理鼠标事件。
    2. MainWindow 类

      • 创建主窗口,并将 ImageCropLabel 设置为其中心小部件。

    运行此代码,你将看到一个可以拖动和调整裁剪区域的图片。你可以根据需要进一步扩展功能,例如添加裁剪确认按钮、保存裁剪结果等。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(12条)

报告相同问题?

问题事件

  • 系统已结题 7月7日
  • 已采纳回答 6月29日
  • 修改了问题 6月28日
  • 创建了问题 6月28日

悬赏问题

  • ¥15 用C语言写离散数学相关问题
  • ¥30 如何用python的GephiStreamer连接到gephi中,把Python和Gephi的具体操作过程都展示,重点回答Gephi软件的调试,以及如果代码的端口在浏览器中无法显示怎么处理
  • ¥15 ansys机翼建模肋参数
  • ¥15 Sumo软件无法运行
  • ¥15 如何在vscode里搭建stata的编辑环境?
  • ¥15 dify知识库创建问题
  • ¥15 如何用C#的chart画1000万个点不卡顿
  • ¥15 爬虫技术找到网上看过房源客户的电话
  • ¥20 代码:Python随机森林反演生物量数据处理问题
  • ¥15 Linux系统的命令行窗口回车变成了换行,无法执行命令了