当前位置 博文首页 > fearlazy:浅谈一个图片查看器的实现
一、思路
? ? 该项目基于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。 原文地址