我在qt标签中显示图像。以下是我的代码:
$(document).ready(function() {
var dlg=$('#dialog').dialog({
title: "jQuery Dialog",
resizable: true,
autoOpen:false,
modal: true,
hide: 'fade',
width:350,
height:275
});
$('#btn').click(function(e) {
e.preventDefault();
dlg.load('test3.php', function(){
dlg.dialog('open');
});
});
});
点击按钮它会向服务器发送请求,并显示从服务器收到的不同图像。如果不超过500次,它工作正常。如果超过该值,则显示此错误
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;
}
并且它不显示图像。然后,如果有人再次发送图像请求,则会显示以下错误:
Qt捕获了一个从事件处理程序抛出的异常。投掷
Qt不支持来自事件处理程序的异常。你必须
重新实现QPixmap::scaled: Pixmap is a null pixmap
并捕获所有例外情况。
我没有得到上面代码中的错误。有人可以告诉我如何解决这个问题吗?
答案 0 :(得分:0)
明显的泄漏是qnam_push_button_clicked_show_image = new QNetworkAccessManager(this);
,它在任何地方都没有平衡删除。 QNAM通常应该创建一次,然后在应用程序的生命周期中重用,而不是为单个请求创建。因此,通过在类成员中转换qnam_push_button_clicked_show_image(与ui相同),您将修复泄漏并提高代码效率。
那就是说,我认为这不是导致你的QPixmap错误的原因。如果您在X11上运行此代码,则QPixmap由X Pixmap资源支持,该资源受各种因素(软件和硬件)的限制。即使从您的代码中没有明显的泄漏,也可能是重复分配大型像素映射会缓慢分割由X管理的内存池,直到它无法为缩放的像素图分配足够大的块然后触发错误。或者它可能是图形堆栈中某处的驱动程序错误。如果在开始破坏之前更改缩放大小增加或减少限制,您是否尝试过?如果是这样,切换到QImage可能有助于减轻对X的压力。
除此之外,代码可以使用一些清理,尤其是多余的QEventLoop用法。我猜这是一种阻止按钮被多次点击直到新图像被加载的方法,但我更倾向于在图像下载时使用button.setEnabled(false)来实现它,因为嵌套的事件循环结合了网络事件是无数重入问题的一个因素,很难调试崩溃/错误。
我也很困惑为什么在堆上分配size
,特别是当它被删除之后,这些if (size)
真的很混乱,因为它们可以理解为if (size->isValid())
而他们真正的意思是if (size != nullptr)
,这几乎可以保证,因为在该线上获得OOM的机会是无穷小的。 (如果你最终耗尽内存,我的猜测可能会发生在上面的readAll()或loadFromData()调用中。)
ps:祝你再次按下该按钮500次以检查是否有助于修复泄漏;)