采集到的图片,用painter绘制是最基础的方式,初学者可能第一次尝试显示图片用的qlabel的setpixmap,用下来会发现卡成屎,第二次尝试用样式表设置背景图,依然卡成屎,最终选用painter的方式,直接drawImage函数绘制解析好的图片,可以通过定义一个信号receiveImage,关联该函数绘制即可,通过调用update方法主动触发paintevent事件,在里面按照需要绘制图片,如果是大量频繁的触发update,Qt内部会合并一些绘制,这样可以大大节约CPU资源。无论是setpixmap还是样式表或者是调色板来设置图片,中间经历过很多的运算,绝大部分都是无关的,而且最终都是调用painter来触发绘制到上面,所以通过painter的方式在这几种选项的情况下是最优的。
绘制图片基本上有三种策略,0-自动调整(超过显示区域尺寸则等比例缩放,不超过则原尺寸) 1-等比缩放(永远等比例缩放,小图会拉伸变模糊) 2-拉伸填充(永远拉伸填充,把这个显示区域填满),为此用户可以自行设定图片拉伸策略,在绘制的时候还要考虑到边框大小的问题,最终绘制的区域要减去边框的大小。
bool AbstractVideoWidget::eventFilter(QObject *watched, QEvent *event)
{if (watched == coverWidget && event->type() == QEvent::Paint) {//矫正颜色if (widgetPara.borderColor == Qt::transparent) {widgetPara.borderColor = palette().shadow().color();}if (widgetPara.textColor == Qt::transparent) {widgetPara.textColor = palette().windowText().color();}QPainter painter;//开始绘制painter.begin(coverWidget);//开启抗锯齿painter.setRenderHints(QPainter::Antialiasing);//绘制边框drawBorder(&painter);//如果图片不为空则绘制图片否则绘制背景if (!image.isNull()) {drawImage(&painter);} else {drawBg(&painter);}//绘制标签和图形信息drawInfo(&painter);//结束绘制painter.end();}return QWidget::eventFilter(watched, event);
}void AbstractVideoWidget::drawBorder(QPainter *painter)
{painter->save();QPen pen;pen.setWidth(widgetPara.borderWidth);pen.setColor(hasFocus() ? widgetPara.focusColor : widgetPara.borderColor);//没有边框则不绘制边框painter->setPen(widgetPara.borderWidth == 0 ? Qt::NoPen : pen);//顺带把背景颜色这里也一并处理(有些场景需要某个控件特殊背景颜色显示)if (widgetPara.bgColor != Qt::transparent) {painter->setBrush(widgetPara.bgColor);}painter->drawRect(rect());painter->restore();
}void AbstractVideoWidget::drawBg(QPainter *painter)
{//已经获取到了宽高不用绘制背景if (videoWidth != 0) {return;}#ifdef openglx//GPU控件可见不用绘制背景if (rgbWidget->isVisible() || yuvWidget->isVisible() || nv12Widget->isVisible()) {return;}
#endifpainter->save();//背景图片为空则绘制文字否则绘制背景图片if (widgetPara.bgImage.isNull()) {painter->setPen(widgetPara.textColor);QFont font;font.setPixelSize(widgetPara.bgTextSize);painter->setFont(font);painter->drawText(rect(), Qt::AlignCenter, widgetPara.bgText);} else {QRect rect = WidgetHelper::getCenterRect(widgetPara.bgImage.size(), this->rect());painter->drawImage(rect, widgetPara.bgImage);}painter->restore();
}void AbstractVideoWidget::drawInfo(QPainter *painter)
{//只有音频和句柄模式不用绘制OSDif (videoWidth == 0 || onlyAudio || widgetPara.videoMode == VideoMode_Hwnd) {return;}//标签位置尽量偏移多一点避免遮挡QRect rect = image.isNull() ? coverWidget->rect() : image.rect();int borderWidth = widgetPara.borderWidth + 5;rect = QRect(rect.x() + borderWidth, rect.y() + borderWidth, rect.width() - (borderWidth * 2), rect.height() - (borderWidth * 2));//将标签信息绘制到遮罩层if (widgetPara.osdDrawMode == DrawMode_Cover) {foreach (OsdInfo osd, listOsd) {if (osd.visible) {painter->save();WidgetHelper::drawOsd(painter, osd, rect);painter->restore();}}}//将图形信息绘制到遮罩层if (widgetPara.graphDrawMode == DrawMode_Cover) {foreach (GraphInfo graph, listGraph) {painter->save();if (!graph.rect.isEmpty()) {WidgetHelper::drawRect(painter, graph.rect, graph.borderWidth, graph.borderColor);}if (!graph.path.isEmpty()) {WidgetHelper::drawPath(painter, graph.path, graph.borderWidth, graph.borderColor);}if (graph.points.size() > 0) {WidgetHelper::drawPoints(painter, graph.points, graph.borderWidth, graph.borderColor);}painter->restore();}}
}void AbstractVideoWidget::drawImage(QPainter *painter)
{if (image.isNull()) {return;}//标签位置尽量偏移多一点避免遮挡QRect rect = image.isNull() ? coverWidget->rect() : image.rect();int borderWidth = widgetPara.borderWidth + 5;rect = QRect(rect.x() + borderWidth, rect.y() + borderWidth, rect.width() - (borderWidth * 2), rect.height() - (borderWidth * 2));//将标签信息绘制到图片上if (widgetPara.osdDrawMode == DrawMode_Image) {foreach (OsdInfo osd, listOsd) {if (osd.visible) {QPainter painter;painter.begin(&image);//painter.setRenderHints(QPainter::Antialiasing);WidgetHelper::drawOsd(&painter, osd, rect);painter.end();}}}//将图形信息绘制到图片上if (widgetPara.graphDrawMode == DrawMode_Image) {foreach (GraphInfo graph, listGraph) {QPainter painter;painter.begin(&image);//painter.setRenderHints(QPainter::Antialiasing);if (!graph.rect.isEmpty()) {WidgetHelper::drawRect(&painter, graph.rect, graph.borderWidth, graph.borderColor);}if (!graph.path.isEmpty()) {WidgetHelper::drawPath(&painter, graph.path, graph.borderWidth, graph.borderColor);}if (graph.points.size() > 0) {WidgetHelper::drawPoints(&painter, graph.points, graph.borderWidth, graph.borderColor);}painter.end();}}//绘制图片painter->save();painter->drawImage(imageRect, image);painter->restore();
}
上一篇: 七夕节主题策划活动方案