QT QPixmap load image defeat - qt

qDebug() << QFileInfo(":/images/123.jpg").exists();
QPixmap myPix;
myPix.load(":/images/123.jpg");
if(myPix.isNull())
{
qDebug() << "Failed to load image" ;
}
true
Failed to load image
Here is the code and output. It bothers me a lot of time.

it look like the res is corrupt... and cant be loaded.
you should verify that the res is loaded properly:
if(myPix.load(":/images/123.jpg"))
{
....
}
like in the doc stated (https://doc.qt.io/qt-5/qpixmap.html#load):
Loads a pixmap from the file with the given fileName. Returns true if the pixmap was successfully loaded; otherwise invalidates the pixmap and returns false.

Related

Getting Pixmap is a null pixmap on calling a function 500 times

I am showing a image in qt label. Below is my code:
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;
}
On clicking push button It will send a request to server and will show a different image received from server. It is working fine if it does't exceeds 500 times. If it exceeds that first this error has been shown
QPixmap::scaled: Pixmap is a null pixmap
and it doesn't show the image. Then if someone again sends a request for an image then it shows the following error:
Qt has caught an exception thrown from an event handler. Throwing
exceptions from an event handler is not supported in Qt. You must
re implement QApplication::notify() and catch all exceptions there.
I am not getting what is the error in the above code. Can someone please tell me how to solve this?
The obvious leak is qnam_push_button_clicked_show_image = new QNetworkAccessManager(this);, which doesn't have a balanced delete anywhere. QNAMs should typically created once, then reused for the lifetime of the application rather than created for a single request. So by turning qnam_push_button_clicked_show_image in a class member (same as ui) you'll fix both your leak and improve the efficiency of the code.
That said, I don't think that's what causes your QPixmap error. If you're running this code on X11, then QPixmap is backed by an X Pixmap resource, which is limited by various factors (software and hardware). Even though from your code there's no obvious leak, it could be that repeatedly allocating large pixmaps slowly fragments the memory pool managed by X, up to the point where it can't allocate a block large enough for the scaled pixmap and then triggers the error. Or it could be a driver bug somewhere in the graphics stack. Have you tried if changing the scaled size increases or decreases the limit before it starts breaking? If so, switching to QImage might help relieving the pressure on X.
Aside from that, the code could use some cleanup, especially that superfluous QEventLoop usage. I'm guessing it's a way to prevent the button from being clicked several times until the new image has been loaded, but I'd much rather implement this using button.setEnabled(false) while the image is downloading, because nested event loops combined with network events is a recipe for countless reentrancy issues and hard to debug crashes/bugs.
I'm also confused about why size is allocated on the heap , especially when it's deleted right after, and these if (size) are really confusing, as they can be understood as if (size->isValid()) while what they really mean is if (size != nullptr), which is pretty much guaranteed as the chance of getting an OOM on that line is infinitesimally low. (if you did eventually run out of memory, my guess is it would likely happen in the readAll() or loadFromData() calls above).
ps: good luck pressing that button another 500 times to check if fixing the leak helped ;)

QT 5.5 - QNetworkReply empty data

I already took at others questions but I didn't find an answer.
I have a problem to print HTML code I download with a QNetworkAccessManager.
I need to log into a website to retrieve this code.
I have a slot like this:
void Aims::slotRequestFinished(QNetworkReply* requestReply)
{
QString data = QString(requestReply->readAll());
qDebug() << data;
}
For the first two steps (connection), I can see the HTML code in the console.
The last step doesn't get any data. There is no redirection nor error.
Now, the stranger part is that when I change my code to show the page into a webview, qDebug doesn't show anything, but the code loaded is shown correctly in the webview.
void Aims::slotRequestFinished(QNetworkReply* requestReply)
{
QString data = QString(requestReply->readAll());
qDebug() << data;
ui->webView->setHtml(data);
}
Well, I can save the content into a file. But I would really like to understand why I can't see anything in qDebug

Constantly generating QPixmap* fails after a number of iterations

I am using the following code in order to generate QPixmap* pointers and then insert them into QHash<QString, QPixmap*> (I will show only the pointers generation code since this is the one that fails).
QPixmap* MyClass::loadImg(QString fileName)
{
QImage qimage(fileName);
if (qimage.isNull()) {
qDebug() << "Cannot load image " << fileName;
}
QPixmap *image = new QPixmap(fileName);
return image;
}
The problem that I have is the following:
For the first about 200 calls the method works fine - it is being called on a loop that iterates through the image files of a directory. Then suddenly the QPixmap* starts returning QPixmap(null) for no apparent reason.QImage is also null when that happens.
I have checked and made sure that the path is fine. Also, I have tried with various sets of images and the same always happens - it runs with no problems the ~200 calls and then starts generating nulls.
Any help would be appreciated.
Thank you.
Just don't create it on heap. QPixmap is implicitly shared.

Retrieve all the file paths from a QDropEvent

I implemented drag and drop in my software. Basically I've got a QTableView which contains file paths. The user must be able to just drag and drop files in the QTableView in order to add them.
I've already done the big of the job but I'm stuck in iterating all the paths contained in the QDropEvent object. I have to implement the dropEvent method.
void Generous::dropEvent(QDropEvent *dropEvent) {
QStringList filePathList;
// Way to iterate dropEvent and append each file path to filePathList.
addFilesToListView(filePathList);
}
How can I do that?
I would guess that a drag and drop using filepaths use the MIME type text/uri-list.
If this is true, you should probably be able to retrieve the data like this:
if (dropEvent->mimeData()->hasUrls())
{
foreach (QUrl url, dropEvent->mimeData()->urls())
{
filePathList << url.toLocalFile();
}
}
Anyway, since I am not sure, the best would be first to check what kind of info is stored inside the drop event, and see where and how you can extract the filepaths:
QStringList availableMimeTypes = dropEvent->mimeData()->formats();
qDebug() << "available MIME types:" << dropEvent->mimeData()->formats() << "\n";
foreach(QString mimeType, availableMimeTypes)
{
qDebug() << "data for MIME type" << mimeType << " :";
qDebug() << dropEvent->mimeData()->data(mimeType) << "\n";
}
You can also create a global list that will keep appending the filePaths on each dropevent. So at the end you will be having a complete list of paths.

Qt: opening qrc pdf with the poppler library

I'm having a bit of trouble with my function for displaying pdf's with the poppler library. The code below is the function in which the problem occurs.
const QString &file is the path to the file
int page is the page on which it has to open
When i set file to a real path (e.g. "/Users/User/Documents/xxx.pdf"), it is no problem to open it. But when i give the path to a qrc file (":/files/xxx.pdf"), it won't work. I want to use it for displaying a user manual for instance, within the application.
I've also tried first making a QFile out of it, opening it and doing readAll, then loading the QByteArray received by doingPoppler::Document::loadFromData(the qbytearray), but it errors already when opening the QFile in ReadOnly mode.
void class::setPdf(const QString &file, int page)
{
Poppler::Document *doc = Poppler::Document::load(file);
if (!doc) {
QMessageBox msgbox(QMessageBox::Critical, tr("Open Error"), tr("Please check preferences: cannot open:\n") + file,
QMessageBox::Ok, this);
msgbox.exec();
}
else{ /*Code for displaying the pdf, which works fine*/
}
}
I hope you can help me,
greetings,
Matt
I've also tried first making a QFile
out of it, opening it and doing
readAll, then loading the QByteArray
received by
doingPoppler::Document::loadFromData(the
qbytearray), but it errors already
when opening the QFile in ReadOnly
mode.
QFile f;
f.setFileName(":/skin/AppIcon16.png");
f.open(QIODevice::ReadOnly);
QByteArray r=f.readAll();
Perfectly reads all data from the resource, have checked it. So i suggest you did something wrong when tried that. Maybe path errors, maybe something else...

Resources