QLabel实现自适应图片大小(可鼠标右击全屏)
引言:首先说下走的弯路,按照固定思维QLabel外面套个QWidget,然后点击布局,让QLabel随着QWidget一起变化,理论上没啥问题,但是实践后,QLabel加载图片进行放大后,QLabel会填充整个widget,无法缩小。所以:
QLabel不要使用布局管理器!!!!
一、修改构造函数
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
ui->VideoShowLabel->setScaledContents(true); //图片自适应label大小
}
setScaledContents是让图片自适应label大小
二、重写resizeEvent函数
当调整窗口使其变化时,paintEvent 函数自动被调用执行,所以重绘label大小(这看起来是不是和 setScaledContents重复了,后续再进行解释)
void Widget::resizeEvent(QResizeEvent *event)
{
ui->VideoShowLabel->resize(ui->widget->size());
}
三、显示图片
我这里是结合opencv获取图片,qt获取图片使用QImage和QPixmap即可
void Widget::OnUpdateFrame()
{
int frameSize_, width, height;
char *image_ = pHdev->getLatestFrame(m_camID,frameSize_,width,height);
cv::Mat image;
if (image_ != NULL)
{
cudaMemcpy(m_pImagedate, image_, frameSize_, cudaMemcpyDeviceToHost);
cv::Mat srcImg(height, width, CV_8UC4, m_pImagedate, cv::Mat::AUTO_STEP);
cv::cvtColor(srcImg, image, cv::COLOR_BGRA2BGR);
cv::line(image,cv::Point(0,image.rows/2),cv::Point(image.cols,image.rows/2),cv::Scalar(255,0,0),1);
cv::line(image,cv::Point(image.cols/2,0),cv::Point(image.cols/2,image.rows),cv::Scalar(255,0,0),1);
}
if(ui->VideoShowLabel->isFullScreen())
{
cv::resize(image, image,cv::Size(ui->VideoShowLabel->width(), ui->VideoShowLabel->height()));
}
else
{
cv::resize(image,image,cv::Size(1280,960));
}
//获取img
QImage img = QImage((const uchar *)image.data, image.cols, image.rows,
image.cols * image.channels(), QImage::Format_RGB888);
QPixmap pixImage = QPixmap::fromImage(img.rgbSwapped());
//显示图像
ui->VideoShowLabel->setPixmap(pixImage);
ui->VideoShowLabel->resize(QSize(pixImage.width(), pixImage.height()));
this->update();
}
四、实现鼠标右击全屏和恢复(实现eventFilter即可)
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
if(watched == ui->VideoShowLabel)
{
if(event->type() == QEvent::MouseButtonPress)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
if(mouseEvent->button() == Qt::RightButton)
{
ui->VideoShowLabel->setWindowFlags(Qt::Window);
ui->VideoShowLabel->showFullScreen();
}
else if(mouseEvent->button() == Qt::LeftButton)
{
ui->VideoShowLabel->setWindowFlags(Qt::SubWindow);
ui->VideoShowLabel->showNormal();
}
}
return QObject::eventFilter(watched,event);
}
}
总结:核心思想就是添加QWiget并进行布局,QWidget控件添加QLabel不使用布局!
问题:(链接:https://blog.csdn.net/emdfans/article/details/52936637)
为什么不直接在窗口上显示QLabel而多加一个QWidget?
假如我们直接在窗口上显示QLabel,那么有两种情况:
一、使直接对QLabel使用布局管理器,二、不使用布局管理器。
不使用布局的情况很明显会使窗口布局错乱适应能力着,或者很难获得窗口真实的大小(我用QDockWidget的大小设定时,当窗口锚接入主窗口时种是遮盖图像的一部分)。
第一种情况:直接对QLabel使用布局管理器:那么情况是,打开界面QLabel自动调节为窗口大小,通过拖动使窗口变大后,窗口内有多余的空间后,布局管理器将QLabel自动放大到窗口大小;看似实现了自动适应窗口大小,但当我们想使窗口变小时问题就出来了,窗口无法缩小,原因是布局管理器内的QLabel大小是整个窗口,窗口没已经是最小了。
当使用QWidget做中间介质后,由于QWidget内没有布局管理器,所以当缩小主窗口时其大小可以改变,而QLabel为从QWidget的(0,0)开始绘制,大小为QWidget大小,所以可以实现与窗口同样大小,显示位置也是布局管理器设置的位置。