PDA

View Full Version : Image resources (png, ico) not rendering in app



xtal256
12th February 2017, 23:37
Hello,

I'm having a problem with my Qt app where none of the icons show when the app is ran. I haven't worked on it in a while, but I know it used to work. It must have stopped working when I upgraded from Qt 4 to 5.
I have created a .qrc file, and all the images are in there. I can also see the "RCC'ing" line in the compile output, so it seems to be compiling the resources correctly. But when I run the app, all the buttons are blank and there are no icons in the menu items. Even the image on the about dialog is not showing.

Here are some details:
Qt 5.1.0
Visual Studio 2010
VS Addin 1.2.2
Windows 7, 64bit

I'm not seeing anything in the debug output, and I don't know where to start looking. Can someone please advise how I can debug this issue?

thanks

nilot
13th February 2017, 09:30
Hello,
Can you show us your qrc file and some lines of code where you create an icon that doesn't work ?

xtal256
13th February 2017, 09:57
My qrc file is just your basic list of files:


<RCC>
<qresource prefix="/">
<file>Window Detective.ico</file>
<file>img/picker.png</file>
<file>img/preferences.png</file>
<file>img/find.png</file>
<file>img/window_large.png</file>
...
</qresource>
</RCC>


The button icons are specified in the .ui files. Qt Designer correctly shows all the icons.

I'm currently looking at the code which loads the image for the About dialog.


void AboutDialog::setupUi() {
...
mainFrame = new QFrame(this);
mainFrameLayout = new QHBoxLayout(mainFrame);
mainFrameLayout->setContentsMargins(10, 10, 0, 0);
leftFrame = new QFrame(mainFrame);
leftFrame->setMinimumSize(QSize(128, 0));
windowImageLabel = new QLabel(leftFrame);
QPixmap windowImage(":img/window_large.png");
windowImageLabel->setGeometry(QRect(QPoint(7, 24), windowImage.size()));
windowImageLabel->setMinimumSize(windowImage.size());
windowImageLabel->setMaximumSize(windowImage.size());
windowImageLabel->setPixmap(windowImage);
mainFrameLayout->addWidget(leftFrame);
...
}


Stepping into the qpixmap.cpp code, I can see it's getting QFileInfo and returning false because the file does not exist. Something about the resource not being valid in QResourceFileEngine::fileFlags.

d_stranz
14th February 2017, 02:03
Try using ":/img/window_large.png". From the documentation for resource files:


Resource Collection Files (.qrc)

The resources associated with an application are specified in a .qrc file, an XML-based file format that lists files on the disk and optionally assigns them a resource name that the application must use to access the resource.

Here's an example .qrc file:

<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>images/copy.png</file>
<file>images/cut.png</file>
<file>images/new.png</file>
<file>images/open.png</file>
<file>images/paste.png</file>
<file>images/save.png</file>
</qresource>
</RCC>

The resource files listed in the .qrc file are files that are part of the application's source tree. The specified paths are relative to the directory containing the .qrc file. Note that the listed resource files must be located in the same directory as the .qrc file, or one of its subdirectories.

Resource data can either be compiled into the binary and thus accessed immediately in application code, or a binary resource can be created and at a later point in application code registered with the resource system.

By default, resources are accessible in the application under the same file name as they have in the source tree, with a :/ prefix, or by a URL with a qrc scheme.
For example, the file path :/images/cut.png or the URL qrc:///images/cut.png would give access to the cut.png file, whose location in the application's source tree is images/cut.png.

xtal256
14th February 2017, 03:07
Oh, with a leading slash after the colon? I'll try that.
I suppose that was something that changed in Qt 5, because it used to work with just the colon.

xtal256
14th February 2017, 09:52
Unfortunately, that didn't work. Many of the other images in my project are already referenced with a leading slash (e.g. ":/img/something.png").

I traced execution into the QResourcePrivate::load function, and res->findNode() always returns -1. It would seem as though the resources aren't being loaded.

anda_skoa
14th February 2017, 10:31
You can use QDir or QDirIterator on ":/" to look into and traverse the resource "file system".

Or the resource inspector of GammaRay (https://www.kdab.com/development-resources/qt-tools/gammaray/)

Cheers,
_

xtal256
15th February 2017, 03:22
Or the resource inspector of GammaRay (https://www.kdab.com/development-resources/qt-tools/gammaray/)
Dude, that looks amazing! It's sort of like what my application (http://windowdetective.sourceforge.net/) is to Windows, but better :)
It should definitely help me in debugging Qt issues.

thanks

xtal256
15th February 2017, 09:49
I used the following code to print all resources:

QDirIterator it(":/", QDirIterator::Subdirectories);
while (it.hasNext()) {
qDebug() << it.next();
}
But none of my images were there. Just a bunch of default Qt resources. So it's clear that the resources are not even getting into the build. They are definitely all there in the .qrc file, and I touched it to make sure the build would run RCC on it.

anda_skoa
15th February 2017, 10:20
Hmm, is your resource part of the application or a library?

I.e. is it in the RESOURCES variable of the .pro file that generates the main executable?

Cheers,
_

xtal256
15th February 2017, 23:10
I don't have a .pro file, I'm using the VS add-in to handle the build. I suspect that I just haven't configured it right, but I don't know exactly how it works. All I know is that it is definitely processing the .qrc file, but obviously it isn't picking up the images and compiling them into the app.

d_stranz
16th February 2017, 04:27
The more important part of anda_skoa's question is whether the resources you are trying to use are in your app EXE or if they are in a DLL you are dynamically loading into your app. If they are in a DLL, you'll need to put a Q_INIT_RESOURCE() macro in main() after your QApplication instance is declared so it will load them properly:



QApplication app( argc, argv );

Q_INIT_RESOURCE( MyDLL );


(assuming your DLL is named "MyDLL.dll")

In Visual Studio, right-click on your qrc file name in the Solution Browser and go to the General properties page. It should look something like the attached screenshot; basically, it should be running rcc on the resource file and putting something in the GeneratedFiles directory.

12339

xtal256
16th February 2017, 10:14
It's in my app's exe, not a dll.

But I think the problem is that the properties that are not correct.
Comparing my property window to your screenshot, the only difference is that my "Additional Dependencies" doesn't list any of the image files like yours does. It just has "%(FullPath);%(AdditionalInputs)". I don't know what %(AdditionalInputs) is.

However, even when I change "Additional Dependencies" to include all my images (using relative paths, like in your screenshot), it still doesn't work. I even tried touching one of the images thinking maybe the incremental build was skipping over them, but nope.

Here is the build output (http://pastebin.com/raw/2tAvQ8ey), at "diagnostic" verbosity.

Lesiok
16th February 2017, 10:23
Try to remove all qrc_*.cpp files from GeneratedFiles folder and then build the project.
If this work something is wrong with the qrc file definition in the project.

ado130
16th February 2017, 10:52
I had the same problem. Try to uncheck "Shadow build" in "Projects".

d_stranz
16th February 2017, 19:46
I had the same problem. Try to uncheck "Shadow build" in "Projects".

The OP is using Visual Studio, not Qt Creator. VS has no explicit concept of shadow builds although it does allow you to set various output and intermediate directories so you can do an out-of-source build in the same way as a shadow build.

I doubt this is the OP's problem. It is probably a dependency issue - maybe the resource files are being excluded from the build because of some VS property setting.

xtal256
16th February 2017, 23:40
I get the feeling that I'm doing something incredibly stupid, like I've actually fixed the problem somehow but I'm accidentally looking at an old exe so I keep seeing the problem. But that can't be it, as I usually run using F5 in Visual Studio. I've done a full clean & build numerous times. I've touched the qrc and image files to make sure the build picks them up. I've done everything I can think of.

When I ran the build with diagnostic verbosity, it didn't give any more information for the RCC'ing stage. Is there a way I can configure Qt's build process to output more detailed information? Perhaps it can tell me whether or not it's reading the image files. Actually, procmon (https://technet.microsoft.com/en-us/sysinternals/bb896645) might come in handy.

d_stranz
17th February 2017, 19:26
Try wiping out everything in the GeneratedFiles directory for whichever build type you are doing. I have found that sometimes the Qt VS plugin gets confused over this. I've sometimes had to manually edit the .vcxproj / .vcproj files to fix build options so that all the right files are being included and built.

xtal256
18th February 2017, 10:36
Ah, I just noticed "GeneratedFiles" in the Visual Studio tree. I thought you were talking about the build output directory (Visual Studio uses the names "Debug" and "Release"), but this one is different. It's not a directory, just a node in the project tree structure. And I don't see the rcc generated file in there, only the moc and ui files. I'll have to read up on how to use the VS add-in, I suspect it should have added the rcc file in there and that's the reason why it's not working.

d_stranz
18th February 2017, 20:14
Hmmm - if things are working as they should, you should have an actual "GeneratedFiles" directory on disk at the same level as your source code. For my projects, the directory structure is typically:



Solution root /
Project root /
Source *.cpp, *.h
Debug / (for Win32 builds)
GeneratedFiles /
Debug /
moc_*.cpp
Release /
moc_*.cpp
qrc_<projectname>.cpp
ui_*.cpp
Release / (Win32 builds)
Resources /
*.png
x64 /
Debug /
Release /


The qrc_<projectname>.cpp file is generated by RCC and is the conversion of your resources into binary strings to be compiled into your project.

Maybe you need to reinstall the Qt VS Add-in?

xtal256
20th February 2017, 04:31
Maybe you need to reinstall the Qt VS Add-in?
Perhaps. Or perhaps I just configured it to use a different directory because I didn't want my project littered with generated files and directories (Visual Studio already adds "Debug", "Release", "ipch", and a bunch of files).

I know "qrc_<projectname>.cpp" exists in the "Debug" directory, and it definitely contains the image data (as byte arrays). But it's not showing in the "GeneratedFiles" directory in Visual Studio. So it mustn't be getting compiled with the rest of the .cpp files.

It's been a while since I last worked on this project, but I remember I used to have to manually add moc and ui files to Visual Studio because I didn't have the add-in to handle all that stuff (I had Visual Studio Express, which can't run add-ins). I later got the add-in, but I can't remember if or how it's supposed to manage all the auto-generated files.

xtal256
20th February 2017, 10:32
Yeah, that did it. Once I added the "qrc_<projectname>.cpp" to GeneratedFiles, it got picked up by the build and now the images are showing correctly.