当前位置 博文首页 > fearlazy:浅谈一个图片查看器的实现

    fearlazy:浅谈一个图片查看器的实现

    作者:[db:作者] 时间:2021-06-18 21:10

    imgviewer.gif


    一、思路

    ? ? 该项目基于Qt编写。具体思路如下:

    ? ? 1.图片查看器类继承于QWidget。

    ? ? 2.使用一个QLabel来显示图片。label是图片查看器的子窗口,它的大小随着图片的大小改变。

    ? ? 3.保存原图以及图片的缩放的比例。使用QPixmap的scaled函数获得缩放后的图片对象。


    二、关键代码

    ? ?1.成员变量:

    ????QLabel*?????m_imgLabel;??//用于显示图片
    ????QPixmap?????m_pixmap;????//保存原图
    ????qreal???????m_fScale;????//保存缩放比例
    ????bool????????m_bMove;?????//是否移动
    ????QPoint??????m_ptPress;???//记录鼠标按下的位置
    


    ? ?2.设置图片

    void?ImageViewer::setPixmap(const?QPixmap&?pixmap)
    {
    ????m_pixmap?=?pixmap;
    ????m_imgLabel->setFixedSize(m_pixmap.size());
    ????m_imgLabel->setPixmap(m_pixmap);
    ????centerImgLabel();
    }
    

    ? ?m_pixmap用于保存原图,m_imgLabel设置和图片的大小一致。


    ? 3.使图片居中

    void?ImageViewer::centerImgLabel()
    {
    ????if(!m_pixmap.isNull())
    ????{
    ????????QPoint?centerPt?=?rect().center();
    ????????int?nWidth?=?m_imgLabel->width();
    ????????int?nHeight?=?m_imgLabel->height();
    ????????m_imgLabel->move(centerPt?+?QPoint(-nWidth/2,-nHeight/2));
    ????}
    }
    

    根据label的大小以及窗口中心点位置反推label居中时的位置。


    4.缩放

    void?ImageViewer::wheelEvent(QWheelEvent?*event)
    {
    ????if(event->delta()?>?0)
    ????{
    ???????m_fScale?*=?1.1;
    ????}
    ????else
    ????{
    ????????m_fScale?*=?0.9;
    ????}
    
    ????int?nWidth?=?m_pixmap.width()*m_fScale;
    ????int?nHeight?=?m_pixmap.height()*m_fScale;
    ????QPixmap?scaledPixmap?=?m_pixmap.scaled(nWidth,nHeight,Qt::KeepAspectRatio,Qt::SmoothTransformation);
    ????m_imgLabel->setFixedSize(nWidth,nHeight);
    ????m_imgLabel->setPixmap(scaledPixmap);
    ????centerImgLabel();
    }
    

    在鼠标滚轮事件中,先计算图片缩放比例,然后根据缩放比例计算出图片的大小。接着使用scaled进行缩放,其中Qt::KeepAspectRatio表示保持宽高的比例。Qt::SmoothTransformation表示平滑变换缩放的图片质量较高。最后保持label的大小与图片大小一致。


    5.拖动操作

    void?ImageViewer::mousePressEvent(QMouseEvent?*event)
    {
    ????if(m_imgLabel->geometry().contains(event->pos()))
    ????{
    ????????m_ptPress?=?event->pos();
    ????????m_bMove?=?true;
    ????}
    }
    
    void?ImageViewer::mouseMoveEvent(QMouseEvent?*event)
    {
    ????if(m_bMove){
    ????????QPoint?offsetPt?=?event->pos()?-?m_ptPress;
    ????????m_imgLabel->move(m_imgLabel->pos()?+?offsetPt);
    ????????m_ptPress?=?event->pos();
    ????}
    }
    
    void?ImageViewer::mouseReleaseEvent(QMouseEvent?*event)
    {
    ????m_bMove?=?false;
    }
    

    通过重写鼠标按下、移动和弹起事件来控制。在鼠标按下事件中判定释放在label之上,如果是则认为允许移动并记录此时的鼠标坐标。接着在鼠标移动事件中判断是否允许移动,若允许则计算出鼠标的偏移量并根据偏移量调整label的位置。最后在鼠标弹起事件中设置不允许移动。


    作者:fearlazy。 原文地址