Qt下图像自定义显示控件

一个简单的继承QWidget的图像显示控件,可以用来显示摄像机采集得图像,支持缩放和图像的拖动,之前用过QLabel,但是在高帧率的采集速度下,会很卡。可以根据需求,自己添加一些绘图操作。使用上,只要在项目中添加两个文件,然后在UI界面中添加一个Widget再提升就可以了。

demo地址:https://download.csdn.net/download/u011941438/9731441

头文件imagewidget.h

#ifndef IMAGEWIDGET_H
#define IMAGEWIDGET_H

#include <QWidget>
#include <QImage>
#include <QPixmap>
#include <QRgb>
#include <QPainter>
#include <QMouseEvent>
class ImageWidget : public QWidget
{
	Q_OBJECT
public:
	//显示风格
	enum EDisplayStyle
	{
		FITWINDOW,//适应窗口
		CENTER_DISPLAY,
	};
	//鼠标操作状态
	enum EmouseOpStatus
	{
		MOS_NONE,//无操作
		MOS_ADJUST_SIZE,//调整图像尺寸
	
	};


public:
	ImageWidget(QWidget *parent=0);
	~ImageWidget();
	void setImage(QImage &image);
	void setImage(const uchar *data, int data_length, int width, int height);
	void setCircleVtr(std::vector<QPoint> _circleVtr);
	//设置图片显示的风格
	void setDisplayStyle(EDisplayStyle _style);
	//设置鼠标点击状态
	void setMouseOpstatus(EmouseOpStatus _EmouseOpstatus);
	//获得当前显示的图片
	QImage getDisplayImage();
	//设置画笔大小
	void setPenSize(int);
	//初始大小
	void initSize();

protected:
	void paintEvent(QPaintEvent * event);
	void mousePressEvent(QMouseEvent *event);
	void mouseReleaseEvent(QMouseEvent *event);
	void mouseMoveEvent(QMouseEvent *event);
	void wheelEvent(QWheelEvent * event);

private :
	//判断点是否在图片中
	bool validatePosInImage(QPoint pos);
	//绘制图片
	void drawImage(QPainter *painter);


private:
	QImage m_DisplayImage;
	QImage m_OriginalImage;
	QVector<QRgb> m_myColorTable;
	QMatrix m_matrix;//缩放移动矩阵
	QMutex m_mutex;//枷锁

	QPoint m_mousePressPoint;
	QPoint m_mouseReleasePoint;
	QPoint m_mouseMovePoint;

	double m_older_move_x;//保存前一次移动距离
	double m_older_move_y;

	int m_move_x;//当前移动距离
	int m_move_y;
	double m_scale;//放大比例

	std::vector<QPoint> m_circleVtr;//画圆

	EDisplayStyle m_Edisplaystyle; //显示风格,1缩放到当前窗口比例 2,原图中心显示
	EmouseOpStatus m_EmouseOpstatus;//鼠标操作状态


	QPoint m_maskPt;
	int m_pen_size;//画笔大小
	bool m_bMoveFlag;

	QPixmap m_penCursor;
	QPixmap m_xpcCursor;
	QCursor m_penQCursor;
	QCursor m_xpcQCursor;

private:
	int m_nw;
	int m_nh;
	int m_niw;
	int m_nih;
	double m_dScale_tmp;
	double m_dScaleW;
	double m_dScaleH;
	double m_adjust_x;
	double m_adjust_y;

	QPainter* m_painter;

};

#endif // IMAGEWIDGET_H
源文件 

#include "imagewidget.h"
#include  <QDebug>
ImageWidget::ImageWidget(QWidget *parent)
	: QWidget(parent)
{
	m_nw=m_nh=m_niw=m_nih=0;
	m_dScale_tmp=m_dScaleW=m_dScaleH=m_adjust_x=m_adjust_y=0.0;
	m_myColorTable.resize(256);
	for(int i = 0; i<256; i++)
		m_myColorTable[i] = qRgb(i,i,i);

	m_older_move_x= m_move_x=0;
	m_older_move_y= m_move_y=0;
	m_mousePressPoint=QPoint(0,0);
	m_mouseReleasePoint=QPoint(0,0);
	m_mouseMovePoint=QPoint(0,0);
	m_scale=1;
	setImage(QImage("test.jpg"));
	m_Edisplaystyle=EDisplayStyle::FITWINDOW;
	m_painter=new QPainter(this);
	m_EmouseOpstatus=MOS_ADJUST_SIZE;

	m_pen_size=4;
	m_bMoveFlag=false;

	m_penCursor=QPixmap("pen.png");
	m_xpcCursor=QPixmap("xpc.png");

	m_penQCursor=QCursor(m_penCursor,0,m_penCursor.height());
	m_xpcQCursor=QCursor(m_xpcCursor,0,m_xpcCursor.height());
}

void ImageWidget::setDisplayStyle(EDisplayStyle _style)
{
	m_Edisplaystyle=_style;
}

void ImageWidget::setMouseOpstatus(EmouseOpStatus _EmouseOpstatus)
{
	m_EmouseOpstatus=_EmouseOpstatus;
	
}
ImageWidget::~ImageWidget()
{

}

void ImageWidget::paintEvent(QPaintEvent * event)
{
	Q_UNUSED(event);
	QPainter  painter_tmp(this);
	//第一步 画图片
	drawImage(&painter_tmp);
}

void ImageWidget::setImage(QImage &image)
{
	QMutexLocker lock(&m_mutex);
	if (image.isNull())
	{
		return;
	}
	
	if (m_DisplayImage.isNull()||m_DisplayImage.size()!=image.size()||m_DisplayImage.format()!=image.format())
	{
		m_OriginalImage=m_DisplayImage=image;

		return;
	}
	int bpp = image.depth()/8;
	setImage(image.bits(),image.width()*image.height()*bpp,image.width(),image.height());



}
void ImageWidget::setImage(const uchar *data, int data_length, int width, int height)
{ 
	//得到图像的位深
	int Dst_bpp=m_DisplayImage.depth()/8;
	int Src_bpp=data_length/(width*height);
	//如果当前图像的大小和位深和要显示的图像一样则直接内存拷贝就行
	if (Dst_bpp==Src_bpp&&m_DisplayImage.width()==width&&m_DisplayImage.height()==height)
	{
		memcpy(m_DisplayImage.bits(),data,data_length);
	}
	else
	{
		QImage::Format fmt;
		//否则,就要确定图像的类型
		switch (Src_bpp)
		{
		case 1:
			fmt=QImage::Format_Indexed8;
			break;
		case 3:
			fmt=QImage::Format_RGB888;
			break;
		case 4:
			fmt=QImage::Format_ARGB32;
			break;
		default:
			return;
		}
		//重新为图像赋值
		m_DisplayImage=QImage(data,width,height,fmt);
		if (fmt==QImage::Format_Indexed8)
		{
			m_DisplayImage.setColorTable(m_myColorTable);
		}

	}
	this->update();

}

void ImageWidget::setCircleVtr(std::vector<QPoint> _circleVtr)
{
	m_circleVtr=_circleVtr;
	update();
}

void ImageWidget::mousePressEvent(QMouseEvent *event)
{
	m_mousePressPoint=event->pos();
	//m_mouseMovePoint=QPoint(-1,-1);
	m_mouseReleasePoint=QPoint(-1,-1);
	if (event->button()==Qt::RightButton)
	{
		switch (m_EmouseOpstatus)
		{
		case MOS_NONE:
			break;
		default:
			m_EmouseOpstatus=MOS_ADJUST_SIZE;
			break;
		}
	} 
	else if (event->button()==Qt::LeftButton)
	{

		switch (m_EmouseOpstatus)
		{
		case MOS_NONE:
			break;
		case MOS_ADJUST_SIZE:
			m_bMoveFlag=true;
		default:
			break;
		}
	}
	update();
}
void ImageWidget::mouseMoveEvent(QMouseEvent *event)
{
	m_mouseMovePoint=event->pos();

	switch (m_EmouseOpstatus)
	{
	case ImageWidget::MOS_NONE:
		break;
	case ImageWidget::MOS_ADJUST_SIZE:
		if (m_bMoveFlag)
		{
			m_move_x=m_mouseMovePoint.x()-m_mousePressPoint.x();
			m_move_y=m_mouseMovePoint.y()-m_mousePressPoint.y();
		}
		break;
	default:
		break;
	}
	update();

}
void ImageWidget::mouseReleaseEvent(QMouseEvent *event)
{
	if (event->button()==Qt::LeftButton)
	{
		m_mouseReleasePoint=event->pos();

		switch (m_EmouseOpstatus)
		{
		case ImageWidget::MOS_NONE:
			break;
		case ImageWidget::MOS_ADJUST_SIZE:
			m_move_x=m_mouseReleasePoint.x()-m_mousePressPoint.x();
			m_move_y=m_mouseReleasePoint.y()-m_mousePressPoint.y();
			m_older_move_x+=m_move_x;
			m_older_move_y+=m_move_y;
			m_move_x=0;
			m_move_y=0;
			m_bMoveFlag=false;
			break;
		default:
			break;
		}  
	}
	update();
}

void ImageWidget::wheelEvent(QWheelEvent * event)
{
	//得到滚轮转动的数值
	QPoint numDegrees = event->angleDelta() / 8;

	double iw=m_DisplayImage.width();
	double ih=m_DisplayImage.height();
	if (numDegrees.y()>0)
	{
		if (m_EmouseOpstatus==MOS_ADJUST_SIZE)
		{	
			m_scale+=0.2; //放大比例增加0.2
			/*
			//保证以图片中心作为缩放中心
			m_older_move_x-=0.2*(iw/2);
		    m_older_move_y-=0.2*(ih/2);
			*/
		}
	}
	else
	{
		if (m_EmouseOpstatus==MOS_ADJUST_SIZE)
		{
			m_scale-=0.2;
			if(m_scale<0.2)
			{
				m_scale=0.2;
			}
			else
			{
				/*
				m_older_move_x+=0.2*(iw/2);
				m_older_move_y+=0.2*(ih/2);
				*/
			}
		}
	} 
	update();
}


bool ImageWidget::validatePosInImage(QPoint pos)
{
	if (m_DisplayImage.isNull())
	{
		return false;
	}
	//将点击位置转换到图像上
	QPoint mapPos=m_matrix.inverted().map(pos);
	//获取图片大小
	double iw=m_DisplayImage.width();
	double ih=m_DisplayImage.height();
	QRect imgRect(0,0,iw,ih);
	//判断是否在图像内
	return imgRect.contains(mapPos);
}
//绘制图片
void ImageWidget::drawImage(QPainter* painter)
{
	//设置画布大小
	QPixmap buff(this->size());
	//设置画笔
	QPainter p(&buff);
	p.setRenderHint(QPainter::SmoothPixmapTransform);
	//记录图片的缩放比例
	if (!m_DisplayImage.isNull())
	{
		//得到控件大小
		m_nw =this->width();
		m_nh=this->height();
		//得到图片大小
		m_niw=m_DisplayImage.width();
		m_nih=m_DisplayImage.height();
		if (m_Edisplaystyle==FITWINDOW)
		{
			//计算控件和图片的比例
			m_dScaleW=(double)m_nw/(double)m_niw;
			m_dScaleH=(double)m_nh/(double)m_nih;
			//取小比例,保证图片完全显示在控件内
			m_dScaleW=m_dScaleH=qMin(m_dScaleW,m_dScaleH);
			//放大或者缩小图片
			m_dScale_tmp=m_scale*m_dScaleW;    
			m_niw*=m_dScaleW;
			m_nih*=m_dScaleW;

			//调整图片在控件出现的位置
			m_adjust_x=-(m_niw-m_nw)/2+m_older_move_x+m_move_x ;
			m_adjust_y=-(m_nih-m_nh)/2+m_older_move_y+m_move_y ;

		}
		else
		{    
			m_dScale_tmp=m_scale;
			m_adjust_x=-(m_niw-m_nw)/2+m_older_move_x+m_move_x;
			m_adjust_y=-(m_nih-m_nh)/2+m_older_move_y+m_move_y;
		}
		//计算画笔的绘制的转换矩阵
		m_matrix=QMatrix().translate(m_adjust_x,m_adjust_y).scale(m_dScale_tmp,m_dScale_tmp);
		p.setMatrix(m_matrix);
		p.drawPixmap(0,0,QPixmap::fromImage(m_DisplayImage));
	}
	//绘制图片
	painter->drawPixmap(0,0,buff);
}

//获得当前显示的图片
QImage ImageWidget::getDisplayImage()
{
	QMutexLocker lock(&m_mutex);
	return m_DisplayImage;
}
//设置画笔大小
void ImageWidget::setPenSize(int size)
{
	m_pen_size=size;
}
void ImageWidget::initSize()
{
	m_older_move_x= m_move_x=0;
	m_older_move_y= m_move_y=0;
	m_scale=1;
	update();
}




demo地址:https://download.csdn.net/download/u011941438/9731441


                
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值