Qt下图像自定义显示控件
2017-01-07 15:04
477 查看
一个简单的继承QWidget的图像显示控件,可以用来显示摄像机采集得图像,支持缩放和图像的拖动,之前用过QLabel,但是在高帧率的采集速度下,会很卡。可以根据需求,自己添加一些绘图操作。使用上,只要在项目中添加两个文件,然后在UI界面中添加一个Widget再提升就可以了。
头文件imagewidget.h
头文件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) { //设置画 4000 布大小 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(); }
相关文章推荐
- 一个显示 OpenCV Mat 图像的自定义 Qt 控件
- MFC/QT 在控件上实时显示图像
- qt+opencv图像在控件上的显示 槽和信号的定义.
- qt利用委托:QStyledItemDelegate,实现tableview 的表格项的自定义显示,如插入图片,绘制控件
- Qt下结合vtk控件显示深度图像
- 【QT】列表控件之自定义显示
- 一个 Qt 显示图片的控件(继承QWidget,使用QPixmap记录图像,最后在paintEvent进行绘制,可缩放)
- 淡入淡出显示图像控件
- Qt中如果通过QStyle自定义能够跨平台的界面控件
- Opencv显示图像到vc的控件上
- Kodak Imgedit.ocx控件显示tif图像
- 利用MFC的Picture控件显示和处理图像
- 自定义用户控件显示属性分类、描述、默认值
- 将opencv中的图像显示在VC的控件中
- OpenCV学习笔记(9)利用MFC的Picture控件显示图像+播放视频和捕获摄像头画面
- (转)5.1自定义Qt控件(Customizing Qt Widgets)
- VB编写一个能显示百分比的自定义进度条控件
- 在GridView控件中显示图像
- Control Study->AdRotator广告控件显示自定义配置文件中广告以及与DataGrid控件结合使用显示图片(示例代码下载)