首页 Qt 学习之路 2 Qt 学习之路 2(9):资源文件

Qt 学习之路 2(9):资源文件

66 6.2K

上一章节中我们介绍了如何使用QAction添加动作。其中,我们使用QIcon加载了一张 png 图片。那时候我们使用的是 Qt 资源文件。现在我们来仔细了解下 Qt 的资源系统。

Qt 资源系统是一个跨平台的资源机制,用于将程序运行时所需要的资源以二进制的形式存储于可执行文件内部。如果你的程序需要加载特定的资源(图标、文本翻译等),那么,将其放置在资源文件中,就再也不需要担心这些文件的丢失。也就是说,如果你将资源以资源文件形式存储,它是会编译到可执行文件内部。

使用 Qt Creator 可以很方便地创建资源文件。我们可以在工程上点右键,选择“添加新文件...”,可以在 Qt 分类下找到“Qt 资源文件”:

Qt Creator 添加资源文件

点击“选择...”按钮,打开“新建 Qt 资源文件”对话框。在这里我们输入资源文件的名字和路径:

Qt Creator 新建资源文件 对话框

点击下一步,选择所需要的版本控制系统,然后直接选择完成。我们可以在 Qt Creator 的左侧文件列表中看到“资源文件”一项,也就是我们新创建的资源文件:

Qt Creator 资源文件编辑界面

右侧的编辑区有个“添加”,我们首先需要添加前缀,比如我们将前缀取名为 images。然后选中这个前缀,继续点击添加文件,可以找到我们所需添加的文件。这里,我们选择 document-open.png 文件。当我们完成操作之后,Qt Creator 应该是这样子的:

Qt Creator 编辑资源文件

接下来,我们还可以添加另外的前缀或者另外的文件。这取决于你的需要。当我们添加完成之后,我们可以像前面一章讲解的那样,通过使用 : 开头的路径来找到这个文件。比如,我们的前缀是 /images,文件是 document-open.png,那么就可以使用:/images/document-open.png找到这个文件。

这么做带来的一个问题是,如果以后我们要更改文件名,比如将 docuemnt-open.png 改成 docopen.png,那么,所有使用了这个名字的路径都需要修改。所以,更好的办法是,我们给这个文件去一个“别名”,以后就以这个别名来引用这个文件。具体做法是,选中这个文件,添加别名信息:

Qt Creator 添加资源别名

这样,我们可以直接使用:/images/doc-open引用到这个资源,无需关心图片的真实文件名。

如果仔细观察,还会看到资源编辑窗口最下方有一个“语言”。这个可以对资源进行国际化。比如我们新建一个前缀,将语言设置为 fr,再添加一个文件 document-open-fr.png:

Qt Creator 资源语言

我们可以使用:/images/fr/doc-open引用到 document-open-fr.png 这个文件。这个“语言”的作用是,如果 Qt 发现,本机的本地化信息是 fr 的话(QLocale::system().name()返回 fr_FR),则使用:/images/fr/doc-open这个图片;如果不是,则默认使用:/images/doc-open这个。

如果我们使用文本编辑器打开 res.qrc 文件,就会看到一下内容:

<RCC>
    <qresource prefix="/images">
        <file alias="doc-open">document-open.png</file>
    </qresource>
    <qresource prefix="/images/fr" lang="fr">
        <file alias="doc-open">document-open-fr.png</file>
    </qresource>
</RCC>

我们可以对比一下,看看 Qt Creator 帮我们生成的是怎样的 qrc 文件。当我们编译工程之后,我们可以在构建目录中找到 qrc_res.cpp 文件,这就是 Qt 将我们的资源编译成了 C++ 代码。

66 评论

adfae 2012年11月23日 - 23:12

我用的是4.8.3,资源总是没法编译,这是为什么呀?

process_begin: CreateProcess(NULL, bin\rcc.exe -name resb ..\gdfdg\resb.qrc -o release\qrc_resb.cpp, ...) failed.
make (e=2): 系统找不到指定的文件。
mingw32-make[1]: *** [release/qrc_resb.cpp] Error 2

我用的是ico图片.

回复
DevBean 2012年11月24日 - 12:10

看错误信息,是不是文件名写错了,或者 rcc 没有找到?

回复
adfae 2012年11月25日 - 00:54

4.8.3似乎有bug,按网上的方法算是解决了,应该是rcc没有被找到.
4.8.3出来的时间不短呀,没想到还会有bug.
实际上我都搞不清楚它是说rcc没找到还是资源没找到...

回复
黄坤哲 2016年7月2日 - 20:25

应该是安装QT的时候没有配置安装环境,建议重新配置下环境变量

回复
斯啦丝拉 2013年1月9日 - 08:34

"我们可以使用 :/images/fr/doc-open 引用到 document-open-fr.png 这个文件。这个“语言”的作用是,如果 Qt 发现,本机的本地化信息是 fr 的话(QLocale::system().name() 返回 fr_FR),则使用 :/images/fr/doc-open 这个图片;如果不是,则默认使用 :/images/doc-open 这个。"
我照楼主所说的做了,可是无法实现自动切换,是不是还需要手动书写相关代码啊。

回复
豆子 2013年1月9日 - 16:50

由于在 Qt Creator 中强制要求添加前缀,因此 lang 属性的作用不是很大。因为不允许有相同的前缀,也就不能仅使用 lang 进行区分。如果你是手动编辑 qrc 文件,不添加前缀的话,就可以使用 lang 进行区分了。

回复
qreerq 2018年1月5日 - 02:49

豆子老师如果先设置不同的语言的话就可以取一样的前缀了, 可是这时编译器会"Warning: potential duplicate alias detected: xxx" 这样好吗

回复
马小巾 2013年7月23日 - 13:56

豆子,你好!有点问题想向你请教一下:
在Windows上用Qt creator(同时创建ui界面),点击pushButton让LineEdit显示自己写的函数跑出的结果,该怎样写?不知道我说清楚了不,函数比如就是C=a+b,a=1,b=2

回复
豆子 2013年7月23日 - 21:05

你可以在 pushButton 的 SLOT 里面调用自己的函数获得结果,比如是 C,然后用 lineEdit 的 setText() 函数设置。

回复
马小巾 2013年7月24日 - 11:23

可以发过来一个吗?菜鸟出错了,很纠结, 😥 跪求,不胜感激啊 !

回复
豆子 2013年7月24日 - 13:09

这个我也不清楚你是要怎样的需求,最好还是自己研究下吧

回复
lmd 2013年8月7日 - 10:45

豆子哥,我按照你说的添加了资源,程序能够运行,但是未能显示图片出来,也没有生成qrc_res.cpp文件,是不是我少了哪一步?

回复
豆子 2013年8月7日 - 11:23

首先看看在 IDE 中是不是有预览的图片,如果没有的话,可能是因为路径的问题。另外还有可能是图片插件之类没有加载

回复
enockipp 2013年8月13日 - 10:59

我和lmd的问题一样,在IDE里面图片名字前能看到小图片,但是没生成qrc_res.cpp,程序也不能显示图片,是图片插件问题么?我加载的是png格式的

回复
豆子 2013年8月13日 - 14:15

png 格式是 Qt 内置支持的,不需要插件,这样就不确定到底什么问题了,只能具体分析下

回复
乔玉东 2013年11月5日 - 18:45

我的也出现这样的问题,不知道该怎么解决。

回复
豆子 2013年11月5日 - 19:31

理论上应该是正常的,不知道会不会哪里设置问题?方便的话做个测试项目看看

回复
乔玉东 2013年11月10日 - 18:52

谢谢了, 重新构建项目,qmake 一次,所有的图标都出来了。

回复
liveinliving 2019年9月1日 - 21:52

对,我的也是,手工把目录清理下,重新构建就好了

Frost Wong 2014年4月2日 - 20:42

我的正常。qt creator 5.2.1

回复
Bill 2015年7月31日 - 20:28

谢谢,用同样的方法解决了

回复
hai 2013年11月10日 - 21:58

openAction = new QAction(QIcon(":/images/document-open.png"),tr("&Open..."),this);
资源文件是按照你上述方式设置的,图标运行不出来,
这句代码改为
openAction = new QAction(QIcon("D:/Qt/qtworkspace/MainWindow/images/document-open.png"),tr("&Open..."),this);
图标可以运行出来,只是为什么啊?
注:D:/Qt/qtworkspace/MainWindow/images/document-open.png是图标文件的绝对路径

回复
豆子 2013年11月11日 - 09:48

试试重新运行下 qmake 再编译,要么直接全部 clean 掉重新编译。另外注意看看 IDE 里面的 qrc 文件中是不是正常显示图标

回复
alextangchao 2019年5月6日 - 21:18

亲测 “清除所有项目“ 后 ”qmake“ 然后再 ”构建项目“ 再 ”run“ 就显示出图片了

回复
黄弘玄 2014年1月22日 - 23:27

其实,很多时候自己出现了问题,看看下面的回复就能解决啊。谢谢楼主,谢谢关注楼主的所有人。只有不断的出现问题,才会走得更远。坚持学习!

回复
sherry 2014年4月29日 - 13:37

添加了资源以后,是不是有别名了,就不能再用文件名了?我的程序就是这样,这样正常吗?

回复
豆子 2014年4月29日 - 15:03

如果你在资源文件中指定了别名就需要使用别名了,如果不想使用别名就不要设置别名。

回复
sherry 2014年4月29日 - 15:43

谢谢!

回复
wenmd 2014年7月10日 - 10:34

openAction = new QAction(QIcon(":/images/b.png"), tr("&Open..."), this);
我将你的代码中那句改成了上面那句,也就是没用用别名,我也没有给资源文件起别名,但为什么出来的exe中没有显示图片啊?新手入门,多多指教啊

回复
豆子 2014年7月11日 - 22:37

试下右键运行 qmake,或者重新构建,再运行试试。如果路径没有错误的话,可能是资源文件没有编译。

回复
wenmd0703 2014年7月15日 - 15:46

谢谢博主回答,不过依然不能显示

回复
epr 2015年3月23日 - 13:08

vs2010中使用qt,怎么使用资源文件啊?我的工具栏图标(icon)在程序运行时显示不出来

回复
豆子 2015年3月27日 - 11:02

如果不是路径问题,最好重新运行下 qmake 看看能不能显示

回复
Charis Chen 2015年4月7日 - 22:47

豆子豆子,问问你这样的报错是什么问题啊, 之前不能显示图片,然后重新构建了之后就不能运行了>-<
NMAKE:-1: error: U1073: 不知道如何生成“..\res.qrc”
NMAKE:-1: error: U1077: “"C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\BIN\amd64\nmake.exe"”: 返回代码“0x2”

回复
豆子 2015年4月8日 - 09:51

这个没有遇到过,是不是因为环境问题,导致找不到处理 qrc 的编译器或规则?

回复
Luck 2015年5月4日 - 15:14

windows下 绝对 相对路径都试了 死活不出图片也clean了也 qmake了

回复
2015年5月6日 - 16:54

那个图标不能显示的问题
我一开始也不能显示
看了评论之后才知道
去了生成的文件夹里面根本没有qrc_res.cpp文件
然后我把生成的文件全删了
然后打开QT先点了绿三角下面的下面的锤子
再去文件夹里看就有cpp了
不过不知道为啥 不用别名还是不能显示图标 用了别名才显示出来

回复
豆子 2015年6月3日 - 11:11

如果使用别名可以显示,有可能是因为路径的问题。

回复
xie 2015年5月15日 - 09:33

你们那些资源图片,比如:document-open.png,哪里可以找到?可以分享一个吗?
谢谢!

回复
豆子 2015年6月3日 - 11:26

图片在网上随便找一下就可以的,不必要一致。

回复
willow 2015年6月8日 - 16:43

楼上各位的错误这里可以解决.http://m.blog.csdn.net/blog/zhxlianxin/8209621

回复
Ada 2015年7月17日 - 11:53

MAC 中路径应该是openAction = new QAction(QIcon(“:/images/images.b.png”), tr(“&Open…”), this);
images路径需要重复才能显示出来是为什么?

回复
豆子 2015年7月20日 - 08:59

:/images 这里的路径可以在 qrc 文件中进行设置

回复
Ada 2015年7月20日 - 12:39

都是按照教程里的方法设置的路径,使用别名的话路径就会变成/images.b.png 但是图片显示不出来。不使用别名的话路径就会生成为:/images/images.b.png 才能显示图片。这是什么原因。。

回复
豆子 2015年7月21日 - 09:14

最新版本的 Mac 上面还没有测试,之前版本是正常的,等有时间测试一下看看。

回复
atsunlun 2015年7月29日 - 22:22

豆子,请问我如何在qt里面调用资源里面的外部EXE应用程序?

回复
豆子 2015年8月1日 - 15:04

资源里面的外部 exe 该如何理解?

回复
atsunlun 2015年8月1日 - 15:07

就是把其他的应用程序EXE,放入到资源中。 然后用QProcess *myProcess=new QProcess; //又可以了*/
myProcess->startDetached("31.exe");
这样执行,不成功。 要怎么做才好呢?

回复
atsunlun 2015年8月1日 - 15:07

QProcess *myProcess=new QProcess; //
myProcess->startDetached(“:/31.exe”);

回复
豆子 2015年8月2日 - 12:20

个人感觉这是不能成功的。资源文件是将资源编译成二进制,同程序一起发布。你当然可以将可执行文件(例如 exe)放进 Qt 资源文件,但是,资源文件是 Qt 自有的机制,操作系统不能理解,也就不能运行。一种可行的方法是,将这个 exe 从资源文件读出,保存到某个位置(例如,临时文件夹)在从那个位置执行。值得指出的是,这种嵌入 exe 的做法并不是常规做法,除非有必须的原因,否则不应该这么做。正确的做法应该是为你的程序添加依赖包(例如使用 msi、rpm 等机制)。

回复
atsunlun 2015年8月2日 - 12:22

我明白了,谢谢豆子老师的答复。

回复
吴军旗 2015年12月24日 - 17:28

重新构建项目,图片可以显示出来

回复
ycr 2016年1月29日 - 19:55

例子里面描述有错误:
"我们可以使用:/images/fr/doc-open引用到 document-open-fr.png 这个文件"
这里无需加上多国语言的前缀 fr, 直接 :/images/doc-open即可.

回复
evergarden 2020年1月10日 - 12:14

我在manjaor下试过了,这样其实只是引用到了/images/doc-open这个文件。
我在manjaro下是这样实现自动切换的:
在/images前缀 添加文件 doc-open.png,别名为doc-open
新建前缀/images,语言选择ch,添加文件doc-open_ch.png,别名doc-open
在mainwindow.cpp中
使用:/images/doc-open。就可以实现自动切换了。

回复
小新 2016年5月9日 - 02:28

请问 我的资源文件能够加载出来, 也能够在程序中显示出来, 可是 文章最后说会生成一个 qrc_XXX.cpp 没有找到, 是怎么回事呢?

回复
豆子 2016年5月10日 - 15:24

这个文件一般会在 debug 或者 release 文件夹下

回复
小新 2016年5月10日 - 16:20

好的, 谢谢告知, 我找一下.

回复
sheldon zuo 2016年5月30日 - 22:43

两个前缀不一样,调用的图片当然不一样

回复
lisa 2016年10月20日 - 19:28

豆子,我在构建的时候报了 out of memory allocating xxx bytes的错误,经常排查,发现当资源文件改小一点就没问题了,我的res文件夹总共大小9.05MB,这个也不算大吧。现在担心无法再加入新的资源文件了。QT creator里是否有关于资源文件大小的限制?

回复
豆子 2016年10月20日 - 21:41

这个没有听说过,应该没有限制的。如果一个资源文件过大,把它分成几个小的资源文件试试看,可不可以规避这个问题呢?

回复
lisa 2016年10月21日 - 09:23

还不会呢。找下相关资料先。:)

回复
Mindy 2017年3月14日 - 20:23

请问一下,我找不到系统资源文件可以加载,应该是安装的时候这一部分没有,请问一下应该怎么下载这些系统资源文件呢?

回复
SCurry 2017年3月15日 - 09:26

求问菜单栏没显示是啥问题呀~QMenu那里。代码都是复制的你的~

回复
豆子 2017年3月16日 - 22:09

看你的系统是什么版本?可能会在系统集成的菜单栏

回复
小白 2017年4月5日 - 16:58

发现当不起别名的话输入文件名可以显示,起别名就只能用别名显示了,不知道原因

回复
evergarden 2020年1月10日 - 12:21

豆子你好,关于“资源国际化”这一部分,我的实验结果与教程有一些不同的地方。
我的系统是manjaro,本机语言为中文(ch)。
使用教程上的办法,我并没有实现自动切换。
我在manjaro下是这样实现自动切换的:
在/images前缀 添加文件 doc-open.png,别名为doc-open
新建前缀/images,语言选择ch,添加文件doc-open_ch.png,别名doc-open
在mainwindow.cpp中
使用:/images/doc-open。就可以实现自动切换了。
这样,运行的结果使用的是doc-open_ch.png这张图片。
当我把上述第二个前缀的语言选择为fr,文件名改成doc-open_fr.png,别名为doc-open时,由于我的电脑本机语言
是中文,运行结果使用的是doc-open.png这张图片。
这样,我就在manjaro上实现了自动切换。

回复

回复 xie 取消回复

关于我

devbean

devbean

豆子,生于山东,定居南京。毕业于山东大学软件工程专业。软件工程师,主要关注于 Qt、Angular 等界面技术。

主题 Salodad 由 PenciDesign 提供 | 静态文件存储由又拍云存储提供 | 苏ICP备13027999号-2