QT学习笔记(四)——在QLabel显示的影像上画图形,并和影像同步放大缩小

4 篇文章 0 订阅

实现在QLabel显示的影像上画图形,并和影像同步放大缩小

关于影像在QLabel的显示,如何随鼠标滚轮实现放大缩小,可以参考我的上一篇博客
QT学习笔记(三)——vs2019+Qt实现打开影像并以鼠标为中心用滚轮控制图片缩放
本篇博客接着这个继续实现如何在QLabel打开的图像上画一个形状(以矩形为例),并且能让这个图形和影像一起随鼠标滚轮放大缩小。

1.首先新建一个myLabel类,重写myLabel的paintEvent方法。

这个方法的目的是保证你能在这个myLabel类生成的对象中画图并显示

//myLabel.h
#include <qlabel.h>
#include <QPainter>
#include <QPoint>
#include <QColor>
#include <QPen>
#include <QDebug>
class myLabel :
    public QLabel
{
    Q_OBJECT
public:
    myLabel(QWidget* parent = nullptr);
    //~myLabel();
    //重写绘制事件
    virtual void paintEvent(QPaintEvent* event) override;
    void DrawRangle(int x, int y, int w, int h);
   
    int x;
    int y;
    int w;
    int h;
};
//myLabel.cpp
#include "myLabel.h"

myLabel::myLabel(QWidget *parent):QLabel(parent) {}

void myLabel::DrawRangle(int xx, int yy, int hh, int ww)
{
    x = xx;
    y = yy;
    w = ww;
    h = hh;

    update();
}
//重写绘制事件
void myLabel::paintEvent(QPaintEvent* event)
{
    QLabel::paintEvent(event);//必须有,才能让背景图片显示出来
    QPainter painter(this);
    QPen pen;
    pen.setColor(Qt::blue);
    pen.setWidth(5);
    painter.setPen(pen);
    painter.drawRect(QRect(x, y, w, h));
    painter.end();
}

2.然后在tstQt中将myLabel.h头文件包含进去,并加入新的成员变量(矩形框)

并在tstQt类中将之前定义的imgLabel的变量类型从QLabel改为自己定义的myLabel,即在tstQt.h中

 myLabel* imgLabel;//图像显示框
//加入新的成员变量
QPoint onept;//矩形左上角点在影像中的坐标
int w;//矩形宽度
int h;

同时,在tstQt.cpp中的InitImage()函数中,将imgLabel的初始化修改为:

imgLabel = new myLabel(dock_Image);

并在该函数末尾添加:

    w = 50;
    h = 50;
    onept.setX(50);
    onept.setY(50);
    imgLabel->DrawRangle(onept.x(), onept.y(), w,h);

这时候运行,就可以看到多了一个蓝色的矩形框了,但是这个矩形相对于label的左上角点的固定的,当鼠标放缩影像时,矩形框不会跟随放缩。因此需要修改wheelevent()函数,下面直接放上该函数的完整代码:

void tstQt::wheelEvent(QWheelEvent* event)
{
    int dockWin_pos = scrollArea->geometry().y()+dock_Image->geometry().y();
    int pp = scrollArea->pos().y();
    QPoint pt = onept;//要画的矩形左上角点

    QScrollBar* tmph = scrollArea->horizontalScrollBar();
    QScrollBar* tmpv = scrollArea->verticalScrollBar();
    QPoint pos = event->pos();//得到当前鼠标在窗口的位置
    QRect tmplab = imgLabel->geometry();//获得imglabel的位置

    int th = pos.x() - tmplab.x();
    int tv = pos.y() - tmplab.y() - dockWin_pos;//缩放前鼠标点在label中的坐标,这里的79是窗体标题的高度

    imgLabel->setPixmap(QPixmap::fromImage(m_image));      // 这一句是为了防止自适应窗口之后进行放缩图像分辨率变低,所以label重新加载原始影像
    double ratio = (double)m_image.height() / (double)m_image.width();//图像的比例
    QPoint numDegrees;                                     // 定义指针类型参数numDegrees用于获取滚轮转角
    numDegrees = event->angleDelta();                      // 获取滚轮转角
    int step = 0;                                          // 设置中间参数step用于将获取的数值转换成整数型
    if (!numDegrees.isNull())                              // 判断滚轮是否转动
    {
        step = numDegrees.y();                             // 将滚轮转动数值传给中间参数step
    }
    event->accept();                                       // 获取事件
    int currentWidth = imgLabel->width();                  // 获取当前图像的宽
    int currentHeight = imgLabel->height();                // 获取当前图像的高

    double stepr = (double)(step) / (double)(currentWidth);  //   (1.0+stepr)为放缩比例=r

    currentWidth += step;                                  // 对当前图像的高累加
    currentHeight += (int)(step*ratio+0.5);                    // 对当前图像的宽累加(四舍五入)

    double r = (double)currentWidth / (double)m_image.width();//始终计算相对于原影像的放缩比例,用来计算所画点放缩后的坐标

    int x = onept.x() * r+0.5;
    int y = onept.y() * r + 0.5;
    int wtmp = w * r ;
    int htmp = h * r ;

    if (step > 0)                                          // 判断图像是放大还是缩小
    {
        QString imgsize = QString("图像放大,尺寸为:%1 * %2")
            .arg(currentWidth).arg(currentHeight);
        qDebug() << imgsize;                               // 打印放大后的图像尺寸
    }
    else
    {
        QString imgsize = QString("图像缩小,尺寸为:%1 * %2")
            .arg(currentWidth).arg(currentHeight);
        qDebug() << imgsize;                                // 打印缩小后的图像尺寸
    }
    imgLabel->resize(currentWidth, currentHeight);          // 通过更新图像显示控件的大小来更新图像大小

    int move_x = stepr * th + 0.5;
    int move_y = stepr * tv + 0.5;

    tmph->setValue(tmph->value()+ move_x);
    tmpv->setValue(tmpv->value() + move_y);

    //对于矩形进行刷新
    //imgLabel->DrawRangle(100, 100, 20, 10);
    imgLabel->DrawRangle(x,y,wtmp,htmp);
}

其实主要就是添加了计算每次刷新时矩形左上角点的坐标,以及新的长宽,每次update()时,会清除上一次画的,所以放缩前的矩形刷新后就不会存在了。运行效果:
打开影像:
在这里插入图片描述
放大:
在这里插入图片描述
缩小:

在这里插入图片描述
放大缩小时,该矩形在图片上的位置是不变的。

3.还有自适应窗口的函数autosize()也要做相应修改

void tstQt::autoSize() // 自适应窗口
{
    imgLabel->setPixmap(QPixmap::fromImage(m_image));
    imgLabel->resize(m_image.width(), m_image.height());
    QImage Img;
    double ImgRatio = 1.0 * imgLabel->pixmap()->toImage().width() / imgLabel->pixmap()->toImage().height();     // 图像宽高比
    double WinRatio = 1.0 * (scrollArea->width() - 2) / (scrollArea->height() - 2); // 窗口宽高比
    if (ImgRatio > WinRatio)        // 图像宽高比大于图像宽高比
    {
        Img = imgLabel->pixmap()->toImage().scaled((scrollArea->width() - 2), (scrollArea->width() - 2) / ImgRatio, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    }
    else                            // 图像宽高比小于等于图像宽高比
    {
        Img = imgLabel->pixmap()->toImage().scaled((scrollArea->height() - 2) * ImgRatio, (scrollArea->height() - 2), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    }
    imgLabel->setPixmap(QPixmap::fromImage(Img));   // 显示图像
    imgLabel->resize(Img.width(), Img.height());

    double r = (double)Img.width() / (double)m_image.width();

    int x = onept.x() * r + 0.5;
    int y = onept.y() * r + 0.5;
    int wtmp = w * r;
    int htmp = h * r;

    imgLabel->DrawRangle(x, y, wtmp, htmp);
}
  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 采用Qt库在QLabel控件上显示图片并在图片上画直线的实现步骤如下: 1. 创建一个QLabel控件,并设置其大小和位置。 ```cpp QLabel* label = new QLabel(this); label->setGeometry(0, 0, 300, 300); ``` 2. 加载图片并设置为QLabel的背景。 ```cpp QPixmap pixmap(":/image/image.png"); // 从资源文件中加载图片 QPalette palette; palette.setBrush(label->backgroundRole(), QBrush(pixmap)); label->setPalette(palette); label->setAutoFillBackground(true); ``` 3. 在QLabel上创建一个QPainter对象,并设置画笔的颜色、宽度等属性。 ```cpp QPainter painter(label); painter.setPen(QPen(Qt::red, 2)); // 设置画笔为红色,宽度为2 ``` 4. 使用QPainter在图片上绘制直线。 ```cpp painter.drawLine(50, 50, 250, 250); // 在图片上绘制一条从(50, 50)到(250, 250)的直线 ``` 5. 更新QLabel控件以显示绘制好的图片。 ```cpp label->update(); ``` 完整代码如下所示: ```cpp #include <QtWidgets> int main(int argc, char *argv[]) { QApplication a(argc, argv); // 创建主窗体 QWidget window; window.setWindowTitle("Qt Display Image"); window.resize(300, 300); // 创建QLabel控件 QLabel* label = new QLabel(&window); label->setGeometry(0, 0, 300, 300); // 加载图片并设置为QLabel的背景 QPixmap pixmap(":/image/image.png"); // 从资源文件中加载图片 QPalette palette; palette.setBrush(label->backgroundRole(), QBrush(pixmap)); label->setPalette(palette); label->setAutoFillBackground(true); // 在QLabel上创建一个QPainter对象,并设置画笔的颜色、宽度等属性 QPainter painter(label); painter.setPen(QPen(Qt::red, 2)); // 设置画笔为红色,宽度为2 // 使用QPainter在图片上绘制直线 painter.drawLine(50, 50, 250, 250); // 在图片上绘制一条从(50, 50)到(250, 250)的直线 // 更新QLabel控件以显示绘制好的图片 label->update(); window.show(); return a.exec(); } ``` 以上代码演示了如何使用QtQLabel显示图片并在图片上绘制直线。图片加载部分使用了资源文件的方式,即图片需要事先添加到Qt的资源文件中。 ### 回答2: 在Qt中,要在QLabel显示图片并在图片上画直线,您可以按照以下步骤进行操作: 1. 创建一个QLabel对象,并将其设置为一个窗口部件(Widget)的子部件,使用QVBoxLayout进行布局。 ```cpp QLabel *label = new QLabel(this); QVBoxLayout *layout = new QVBoxLayout(); layout->addWidget(label); this->setLayout(layout); ``` 2. 加载图片到QPixmap对象中,并将其设置到QLabel中进行显示。 ```cpp QPixmap pixmap("image.png"); label->setPixmap(pixmap); label->setScaledContents(true); // 自适应QLabel的大小 ``` 3. 创建一个QPainter对象来绘制直线。可以在QLabel的paintEvent事件函数中绘制直线。 ```cpp void MyWidget::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.drawPixmap(label->geometry(), pixmap); // 在QLabel的范围内绘制图片 // 绘制直线 painter.setPen(Qt::red); // 设置直线颜色为红色 painter.drawLine(50, 50, 200, 200); // 在图片上画一条直线,起点(50, 50),终点(200, 200) } ``` 这样,您就可以在QtQLabel显示图片并在图片上绘制直线了。希望对您有所帮助! ### 回答3: 在Qt中,要在QLabel显示图片并在图片上画直线,可以通过以下步骤实现: 1. 创建一个QLabel控件,并设置其大小和位置。 ```cpp QLabel *label = new QLabel(this); label->setGeometry(10, 10, 500, 500); ``` 2. 从文件中加载图片,并将其设置为QLabel的背景。 ```cpp QPixmap pixmap("image.jpg"); label->setPixmap(pixmap); ``` 3. 在QLabel上添加一个QPainter对象,并设置其渲染目标为QLabel。 ```cpp QPainter painter(label); ``` 4. 使用QPen设置画笔的颜色、宽度等属性。 ```cpp QPen pen(Qt::red); pen.setWidth(2); painter.setPen(pen); ``` 5. 使用QPainter在图片上画直线。 ```cpp painter.drawLine(10, 10, 300, 300); ``` 这将在图片上从点(10, 10)绘制一条直线到点(300, 300)。 6. 结束绘制并更新QLabel显示。 ```cpp painter.end(); label->update(); ``` 通过以上步骤,你可以在QtQLabel控件上显示图片并在图片上画直线。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值