我正在qt标签中显示图像。以下是我的代码:
void MyClass::onPushButtonClicked(QString myurl)
{
this->setCursor(Qt::WaitCursor);
ui.qtImageLabel->clear();
qDebug()<<QTime::currentTime()<<"MyClass: onPushButtonClicked";
QNetworkAccessManager *qnam_push_button_clicked_show_image;
QNetworkReply *reply;
QNetworkRequest request;
request.setHeader( QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded" );
QUrl url(myurl);
request.setUrl(url);
qnam_push_button_clicked_show_image = new QNetworkAccessManager(this);
if(qnam_push_button_clicked_show_image)
{
QObject::connect(qnam_push_button_clicked_show_image, SIGNAL(finished(QNetworkReply*)),
this, SLOT(onPushButtonClickedRequestCompleted(QNetworkReply*)));
reply = qnam_push_button_clicked_show_image->post(request, url.encodedQuery());
QEventLoop loop;
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
}
}
void MyClass::onPushButtonClickedRequestCompleted(QNetworkReply *reply)
{
qDebug()<<QTime::currentTime()<<"MyClass: onPushButtonClickedRequestCompleted request completed";
if (reply->error() != QNetworkReply::NoError)
{
qDebug() << "Error in" << reply->url() << ":" << reply->errorString();
this->setCursor(Qt::ArrowCursor);
return;
}
QByteArray data = reply->readAll();
QPixmap pixmap;
pixmap.loadFromData(data);
int width;
int height;
//application size can be changed
QRect rec = QApplication::desktop()->screenGeometry();
height = rec.height();
width = rec.width();
qDebug()<<QTime::currentTime()<<width<<","<<height;
QSize *size = new QSize(width,height);
if(size)
{
QPixmap scaledPixmap = pixmap.scaled(*size);
ui.qtImageLabel->setPixmap(scaledPixmap);
}
if(size)
{
delete size;
size = NULL;
}
data.clear();
this->setCursor(Qt::ArrowCursor);
reply->deleteLater();
return;
}
单击按钮时,它将向服务器发送请求,并将显示从服务器接收到的不同映像。如果不超过500次,它的工作正常。如果超过了第一个错误已显示
QPixmap::scaled: Pixmap is a null pixmap
,它没有显示图像。然后,如果有人再次发送图像请求,则显示以下错误:QT遇到了一个事件处理程序引发的例外。投掷QT中不支持事件处理程序的例外。你必须重新实现QApplication::notify()
并在那里捕获所有例外。
我没有得到上述代码中的错误。有人可以告诉我如何解决这个问题吗?
明显的泄漏是qnam_push_button_clicked_show_image = new QNetworkAccessManager(this);
,在任何地方都没有平衡的删除。QNAMS通常应该创建一次,然后在应用程序的使用寿命中重复使用,而不是为单个请求创建。因此,通过转动QNAM_PUSH_BUTTON_CLICKED_SHOW_IMAGE在类成员中(与UI相同),您可以固定泄漏并提高代码的效率。
也就是说,我认为这不是导致您的qpixmap错误的原因。如果您在X11上运行此代码,则QPIXMAP将由X PixMap资源支持,该资源受到各种因素(软件和硬件)的限制。即使从您的代码中没有明显的泄漏,也可能反复分配大型像素慢慢片段片段由X管理的内存池,直到无法为缩放的PixMap分配足够大的块,然后触发错误。或者它可能是图形堆栈中某个地方的驱动程序错误。如果更改缩放尺寸会增加或降低极限在开始破裂之前,您是否尝试过?如果是这样,切换到qimage可能有助于减轻x上的压力。
除此之外,代码还可以使用一些清理,尤其是多余的Qeventloop使用情况。我猜这是一种防止按钮单击几次直到新图像加载的方法,但是我宁愿在下载图像时使用button.setEnabled(false)实现此功能,因为嵌套事件循环组合了网络事件是无数重新进入问题的食谱,很难调试崩溃/错误。
我也对size
为何分配在堆上的原因,尤其是在此之后被删除时,这些if (size)
确实令人困惑,因为它们可以被理解为if (size->isValid())
,而实际上是if (size != nullptr)
,这几乎是如此之多保证在该线上获得OOM的机会是无限的。(如果您最终确实用完了内存,我的猜测是可能发生在readall()或LoadFromData()调用)中。
ps:好运再按下该按钮再500次检查修复泄漏是否有帮助;)