获取PixMap是调用功能500次的空置示例



我正在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次检查修复泄漏是否有帮助;)

相关内容

  • 没有找到相关文章

最新更新