马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
源码地址,环境:QT5.15,MinGW32位
效果演示
导入图片
- QPixmap m_srcPix;
- QPixmap m_scaledPix;
- //从文件导入图片
- m_srcPix.load("D:\\Jolly\\A_0voice_chat\\chapter_explanation\\PictureEdit_demo\\PictureEdit\\images\\1.png");
- //把导入的图片截取到窗口大小
- m_scaledPix = m_srcPix.scaled(ui->label->width(), ui->label->height());
- //在窗口显示图片
- ui->label->setPixmap(m_scaledPix);
复制代码 设置剪裁地域
- //裁剪头像活动窗口
- //设置透明
- this->setWindowFlags(Qt::FramelessWindowHint);
- //设置矩形区域,整个窗口
- this->setGeometry(0, 0, parentWidget()->width(), parentWidget()->height());
- CutDialog *m_cutDialog;
- //头像剪切窗口
- m_cutDialog = new CutDialog(this);
- m_cutDialog->show();
复制代码 创建剪裁小窗口
- CutDialog::CutDialog(QWidget *parent) :
- QWidget(parent)
- {
- setGeometry(0,0, 150, 150);
- m_mouseDown = false;
- }
复制代码 重写剪裁小窗口的鼠标事件
mousePressEvent
- void CutDialog::mousePressEvent(QMouseEvent *event)
- {
- //获取鼠标按下时的位置
- m_startPoint = event->pos();
- //判断按下的是否是鼠标左键
- m_mouseDown = event->button() == Qt::LeftButton;
- }
复制代码 mouseMoveEvent
要是没有启用鼠标追踪,mouseMoveEvent 只有在鼠标按键被按下并且鼠标移动时才会触发,而且是在mousePressEvent触发之后。
当启用鼠标追踪后,不管鼠标按键是否被按下,只要鼠标移动,mouseMoveEvent就会触发
- void CutDialog::mouseMoveEvent(QMouseEvent *event)
- {
- //获取鼠标移动以后的位置
- QPoint dragPoint = event->pos();
- if (m_mouseDown) {
- //pos保存小部件在其父部件中的位置
- QPoint p = QPoint(
- //pos() 是对话框在父窗口中的左上角坐标
- //dragPoint - m_startPoint 计算鼠标移动的偏移量
- //原理: 拖动点相对于对话框的位置保持不变(如从(10,10)点开始拖动,移动后仍抓住该点)
- pos().x()+dragPoint.x() - m_startPoint.x(), // 水平方向
- pos().y()+dragPoint.y()-m_startPoint.y() // 垂直方向
- );
- QPoint dragEndge = p;
- dragEndge.setX(p.x() + rect().width()); // 对话框右下角X坐标
- dragEndge.setY(p.y() + rect().height()); // 对话框右下角Y坐标
- //左上角约束,保证小窗口左上角在父窗口范围内
- p.setX(p.x() < 0 ? 0 : p.x());
- p.setY(p.y() < 0 ? 0 : p.y());
- //右下角约束
- // 确保右下角X ≤ 父窗口宽度
- p.setX(dragEndge.x() > parentWidget()->width()
- ? parentWidget()->width() - rect().width()
- : p.x());
- // 确保右下角Y ≤ 父窗口高度
- p.setY(dragEndge.y() > parentWidget()->height()
- ? parentWidget()->height() - rect().height()
- : p.y());
- //QWidget::move() 对窗口部件的位置进行设置
- move(p);
- /*
- move函数原型
- void move(int x, int y);
- void move(const QPoint &pos);
- */
- }
- }
复制代码 mouseReleaseEvent
开释鼠标时将m_mouseDown 设置为false,避免鼠标右键或其他案件误触发mouseMoveEvent
- void CutDialog::mouseReleaseEvent(QMouseEvent *event)
- {
- m_mouseDown = false;
- }
复制代码 小窗口移动触发父窗口的重绘事件
paintEvent调用机会:
首次表现窗口时
当 PhotoShotDialog 首次表现(例如通过 show() 或 exec())时,系统会自动触发 paintEvent 进行初始绘制。
窗口需要重绘时
窗口被其他窗口遮挡后重新暴露出来
窗口内容发生变化(如子窗口移动、尺寸变化)
调用 update() 或 repaint() 方法强制重绘
子窗口移动时(关键)
当用户拖动 CutDialog时:
CutDialog::mouseMoveEvent() 中调用了 move§ 移动裁剪框
移动利用会自动触发父窗口(PhotoShotDialog)的重绘,由于:
子窗口位置变化导致父窗口的可看法区需要更新
系统自动发送重绘事件到父窗口
- void PhotoShotDialog::paintEvent(QPaintEvent *event)
- {
- QPainterPath painterPath;
- QPainterPath p;
- p.addRect(x(),y(),this->rect().width(), this->rect().height()); //裁剪头像活动窗口 (蓝色矩形)
- //QWidget::geometry()返回一个 QRect 对象。这个对象包含了窗口部件的位置和大小信息
- painterPath.addRect(m_cutDialog->geometry()); //头像剪切窗口 (紫色矩形)
- QPainterPath drawPath = p.subtracted(painterPath); //subtracted 获取除了painterPath区域以外的窗口
- QPainter painter(this);
- painter.setOpacity(0.6); //设置Qt控件透明度 0表示全透明,1表示不透明
- painter.fillPath(drawPath, QBrush(Qt::black));
- }
复制代码 剪裁效果实现
- void PictureEdit::on_pushButton_clicked()
- {
- //直接复制小窗口的图像内容
- QPixmap pix = m_scaledPix.copy(m_psDialog->getCutGeometry());
- //将截图内容重命名,并保存到指定目录
- pix.save("D:\\work\\workspace\\qtstudyspace\\PictureEdit\\images\\cut.png", "png");
- }
复制代码 |