Ampliació: Gestió de Recursos en Qt6

⚠️ Paths relatius vs recursos encastats

El problema amb paths sense qrc:/

Quan uses un path relatiu sense el prefix qrc:/:

Image { source: "logo.png" }

Qt busca el fitxer en aquest ordre:

  1. Relatiu al fitxer QML actual → Busca logo.png al mateix directori que el fitxer QML
  2. Al sistema de fitxers → NO dins de l'executable compilat
  3. NO al sistema de recursos → Per tant, NO funciona en l'executable final distribuït

Demostració del problema:

# Durant el desenvolupament (amb QtCreator al directori del projecte)
./appminRecursos  # ✅ Funciona (troba logo.png al directori font)

# Després de distribuir l'executable
cp appminRecursos /tmp/
cd /tmp/
./appminRecursos  # ❌ NO funciona! (logo.png no està disponible)

✅ Solucions correctes per encastar recursos

Solució 1: Usar el prefix automàtic del mòdul QML

qt_add_qml_module(appminRecursos
    URI minRecursos
    QML_FILES Main.qml
    RESOURCES logo.png
)
// ✅ CORRECTE - Path complet amb el prefix del mòdul
Image { 
    source: "qrc:/qt/qml/minRecursos/logo.png"
}

Explicació: Quan compiles, Qt crea el recurs amb el path complet del mòdul: /qt/qml/URI/fitxer

Avantatges:

Desavantatge:


Solució 2: Definir RESOURCE_PREFIX personalitzat (RECOMANADA)

qt_add_qml_module(appminRecursos
    URI minRecursos
    QML_FILES Main.qml
    RESOURCES logo.png
    RESOURCE_PREFIX "/"  # ← Prefix simple a l'arrel
)
// ✅ CORRECTE - Path curt i clar
Image { 
    source: "qrc:/logo.png"
}

Avantatges:


Solució 3: Separar recursos amb qt_add_resources

qt_add_qml_module(appminRecursos
    URI minRecursos
    QML_FILES Main.qml
)

qt_add_resources(appminRecursos "imatges"
    PREFIX "/img"
    FILES logo.png
)
// ✅ CORRECTE
Image { 
    source: "qrc:/img/logo.png"
}

Avantatges:


Com verificar que els recursos funcionen correctament

Mètode 1: Prova de distribució

# 1. Compila el projecte
cd build/
cmake --build .

# 2. Copia l'executable a un altre directori (sense els fitxers font)
cp appminRecursos /tmp/

# 3. Executa des del directori temporal
cd /tmp/
./appminRecursos

# Si la imatge es veu → ✅ Recursos correctament encastats
# Si la imatge NO es veu → ❌ Estàs usant paths relatius (error!)

Mètode 2: Consola de sortida del QtCreator

Busca missatges durant la compilació com:

-- Generating resources for target appminRecursos
-- qt_add_resources: Processing appminRecursos_imatges

Mètode 3: Debug en temps d'execució

Image {
    source: "qrc:/logo.png"
    
    Component.onCompleted: {
        console.log("Font de la imatge:", source)
        console.log("Status:", status)  // Ready = 1, Error = 3
    }
    
    onStatusChanged: {
        if (status === Image.Error) {
            console.error("Error carregant:", source)
        }
    }
}

Mètode 4: Llistar recursos compilats

# Al directori build/, busca els fitxers .qrc generats
find . -name "*.qrc" -exec cat {} \;

# O usa l'eina rcc (Resource Compiler)
rcc --list appminRecursos_resources_1.qrc

Taula resum: On busca cada tipus de path

Codi QML On busca Funciona en executable? Ús recomanat
source: "logo.png" Sistema de fitxers (relatiu al QML) ❌ NO Mai en producció
source: "qrc:/logo.png" Recursos encastats (executable) ✅ SÍ Sempre en producció
source: "qrc:/qt/qml/URI/logo.png" Recursos encastats (path complet) ✅ SÍ Si no uses RESOURCE_PREFIX
source: "file:///path/logo.png" Path absolut del sistema ❌ NO portable Només per testing local
source: "../images/logo.png" Relatiu al directori del QML ❌ NO Mai

Regla d'or:

SEMPRE usa el prefix qrc:/ per accedir a recursos encastats en l'executable.


Errors comuns i solucions

Error 1: "Cannot open: qrc:/img/logo.png"

Causes possibles:

  1. El fitxer NO està declarat al CMakeLists.txt dins de qt_add_resources o RESOURCES
  2. El PREFIX no coincideix amb el path usat al QML
  3. No s'ha fet Clean All + Rebuild després de modificar recursos
  4. El fitxer físic no existeix o el path és incorrecte

Solució:

# Verifica que el fitxer estigui inclòs correctament:
qt_add_resources(appexempleRecursos "imatges"
    PREFIX "/img"
    FILES
        images/logo.png  # ← Ha d'existir físicament al directori images/
)
// I que el path al QML coincideixi exactament:
Image { source: "qrc:/img/logo.png" }  // PREFIX + nom relatiu

Error 2: "Duplicate resource"

Causa: El mateix fitxer està inclòs dues vegades, per exemple:

Solució: Decideix on vols gestionar els recursos i elimina la duplicació.

# ❌ INCORRECTE - Duplicat
qt_add_qml_module(app
    URI myapp
    RESOURCES logo.png
)
qt_add_resources(app "imgs"
    FILES logo.png  # ← Duplicat!
)

# ✅ CORRECTE - Només en un lloc
qt_add_qml_module(app
    URI myapp
    RESOURCES logo.png
    RESOURCE_PREFIX "/"
)

Error 3: La imatge es veu durant el desenvolupament però no en l'executable

Causa: Estàs usant paths relatius sense qrc:/

// ❌ Funciona en QtCreator, falla en executable distribuït
Image { source: "logo.png" }

Solució: Sempre usar qrc:/

// ✅ Funciona sempre
Image { source: "qrc:/logo.png" }

Important: Paths sempre relatius al CMakeLists.txt

# ✅ CORRECTE - Path relatiu al CMakeLists.txt
qt_add_resources(app "imgs"
    FILES
        images/logo.png
)

# ❌ INCORRECTE - Path absolut (no funciona multiplataforma)
qt_add_resources(app "imgs"
    FILES
        /home/jb/projecte/images/logo.png
)

# ✅ CORRECTE - Usar variable CMAKE per paths absoluts necessaris
qt_add_resources(app "imgs"
    FILES
        ${CMAKE_SOURCE_DIR}/assets/logo.png
)

# ✅ CORRECTE - Paths relatius fora del directori actual
qt_add_resources(app "imgs"
    FILES
        ../shared_resources/logo.png
)

Quan emprar cada mètode?

Situació Mètode recomanat Justificació
Imatges simples del projecte qt_add_resources amb PREFIX curt Simplicitat i claredat
Recursos específics d'un mòdul QML RESOURCES + RESOURCE_PREFIX dins qt_add_qml_module Encapsulació del mòdul
Necessites alias específics Fitxer .qrc tradicional + qt_add_resources Única manera de fer alias
Recursos multiplataforma if(ANDROID) + múltiples qt_add_resources Splash diferents per plataforma
Molts fitxers organitzats en carpetes BASE amb qt_add_resources Mantenir estructura de directoris
Projecte senzill amb pocs recursos RESOURCES dins qt_add_qml_module Tot en un sol lloc

Exemple complet mínim (copiar i enganxar)

Estructura del projecte:

projecte/
├── CMakeLists.txt
├── main.cpp
├── Main.qml
└── logo.png

CMakeLists.txt:

cmake_minimum_required(VERSION 3.16)
project(minRecursos VERSION 0.1 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 REQUIRED COMPONENTS Quick)
qt_standard_project_setup(REQUIRES 6.8)

qt_add_executable(appminRecursos main.cpp)

qt_add_qml_module(appminRecursos
    URI minRecursos
    QML_FILES Main.qml
    RESOURCES logo.png
    RESOURCE_PREFIX "/"  # ← Prefix simple per facilitar l'accés
)

target_link_libraries(appminRecursos PRIVATE Qt6::Quick)

Main.qml:

import QtQuick

Window {
    visible: true
    width: 400
    height: 300
    title: "Exemple Recursos"
    
    Image {
        source: "qrc:/logo.png"  // ← Sempre amb qrc:/
        anchors.centerIn: parent
        fillMode: Image.PreserveAspectFit
        
        // Debug per verificar la càrrega
        onStatusChanged: {
            if (status === Image.Ready) {
                console.log("✅ Imatge carregada correctament")
            } else if (status === Image.Error) {
                console.error("❌ Error carregant la imatge:", source)
            }
        }
    }
}

main.cpp: (Codi estàndard Qt Quick)

#include <QGuiApplication>
#include <QQmlApplicationEngine>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    
    const QUrl url(u"qrc:/qt/qml/minRecursos/Main.qml"_qs);
    engine.load(url);
    
    if (engine.rootObjects().isEmpty())
        return -1;
    
    return app.exec();
}

Compilar i provar:

mkdir build && cd build
cmake ..
cmake --build .

# Provar que funciona fora del directori
cp appminRecursos /tmp/
cd /tmp/
./appminRecursos  # Ha de mostrar la imatge correctament

Compatibilitat de versions Qt

Nota per als alumnes: Si treballeu amb Qt 6.0 o 6.1, actualitzeu a Qt 6.2+ per seguir aquests exemples.


Consells finals

  1. Sempre empra qrc:/ per a recursos encastats - És l'única manera de garantir que funcionarà en l'executable distribuït

  2. Defineix RESOURCE_PREFIX "/" per simplicitat - Evita paths llargs i confusos

  3. Prova l'executable fora del directori del projecte - Si funciona, els recursos estan ben encastats

  4. Usa noms de fitxer descriptius - Evitaràs necessitar alias complicats

  5. Organitza els recursos en carpetes lògiques - Usa BASE per mantenir l'estructura

  6. Fes Clean + Rebuild després de canviar recursos - Qt no sempre detecta canvis en fitxers de recursos

  7. Afegeix debug de status a les imatges - Et permetrà detectar errors de càrrega ràpidament