Qt:避免在字符串更改时重建应用程序

Posted

技术标签:

【中文标题】Qt:避免在字符串更改时重建应用程序【英文标题】:Qt : Avoid Rebuilding Applications incase strings change 【发布时间】:2014-01-03 10:13:46 【问题描述】:

我想知道在 QT 应用程序中存储字符串的选项是什么。 我的主要要求之一是不重新构建整个项目或任何文件以防一个字符串发生更改,并将所有字符串放在一个地方。简而言之,我希望将字符串放在一个地方并在应用程序启动期间提取它们

【问题讨论】:

如果您更改单个字符串,您只需要重新构建一个 . cpp 并重新链接对象模块,几乎不需要重新构建完整的项目。 即使你改变了字符串和保存的文件,编译器也会寻找lib和.cpp的时间戳,而cpp的保存时间晚于lib,它会构建一个.cpp然后链接。 我不想重新构建项目。 使用 qt 语言学家和翻译器(tr 函数和相关宏)。然后您将在翻译文件中拥有这些字符串。 【参考方案1】:

我已经使用了上述答案中提到的所有元素。

XMLJSONQSettings 带 Ini 文件、tr()

他们都可以做得很好。我整理了一些关于不同选项的注释:

QTranslator

Qt Linguist 和tr() 标签旨在获取您的常用语言并将其翻译成另一种语言。在没有 Qt Linguist 的情况下跟踪多个版本的英文翻译和修改/发布几乎是不可能的。 Qt Linguist 需要“发布”您的翻译并将它们从 TS 文件(翻译源)转换为优化的 QM 文件。

QM 文件格式是本地化应用程序使用的紧凑二进制格式。它提供了极其快速的翻译查找。

下面是使用翻译文件的样子:

 QTranslator translator;
 translator.load("hellotr_la");
 app.installTranslator(&translator);

http://qt-project.org/doc/qt-4.8/qtranslator.html#details

我认为使用QTranslator 进行一些字符串更改可能是一个奇怪的用例,除非您用于本地化程序。但就像文档说的那样,它针对非常快速的字符串替换查找进行了优化。

QXMLStreamReader

流阅读器是访问 XML 文件的“推荐”方式,或者至少有更好的支持。您编写自己的文件来组织它,或者编写代码来生成 XML。

<STRING_1>Some string</STRING_1>

这是导航到 xml 的样子。

QXmlStreamReader xml;
...
while (!xml.atEnd()) 
      xml.readNext();
      ... // do processing

if (xml.hasError()) 
      ... // do error handling

XML 与 Json 非常相似,但文件更大,开始和结束标签更长。 XML 有更多的股票阅读器。在许多情况下,它也更易于人类阅读,因为很多人都知道 html,而且它们非常相似。

QJsonDocument

Qt 5 中的 JSON 支持看起来非常好。 我还没有用它构建项目它看起来很简单,就访问和设置而言,它看起来就像使用字典或地图或矢量一样。

更新:您只需将指针传递到您的QJsonDocumentQJsonObjectQJsonArray,因为您正在更深入地导航或将更多内容附加到您的Json 文件中。完成后,您可以将其保存为二进制文件,或作为明文、人类可读的文件,并带有适当的缩进和一切!

How to create/read/write JSon files in Qt5

对于许多人来说,Json 似乎正在成为 XML 的替代品。我喜欢使用 Json 保存和加载角色扮演游戏状态的示例。

http://qt-project.org/doc/qt-5/qtcore-savegame-example.html

Q设置

QSettings 是我最喜欢的设置之一,因为它支持了这么久,它是大多数持久设置应该保存和访问的方式。

当我使用它时,为了利用默认值和回退机制,我将它放在我的 main.cpp 中:

 QCoreApplication::setOrganizationName("MySoft");
 QCoreApplication::setOrganizationDomain("mysoft.com");
 QCoreApplication::setApplicationName("Star Runner");

因为有时我发现需要在 windows 中手动编辑这些设置,所以我使用 Ini 格式。

QSettings::setDefaultFormat(QSettings::IniFormat); // also in main.cpp

然后,当我部署我的 exe,并且我想加载特定值而不是硬编码的默认值时,安装程​​序会将主要后备放入

C:/ProgramData/MySoft/Star Runner.ini

当程序在运行时保存更改时,它会保存到:

C:/Users/<username>/AppData/Roaming/MySoft/Star Runner.ini

然后在整个程序中,如果我需要获取设置或设置设置,只需要 3 行代码或更少。

// setting the value
QSettings s;
s.setValue("Strings/string_1", "new string");


// getting the value
QString str;

QSettings s;
str = s.value("Strings/string_1", "default string").toString();

这是您的 ini 文件的样子:

[Strings]
string_1=default string

QSettings 是如果您要存储一些要在部署或运行​​时更改的字符串的方法。 (或者如果现在选中了一个复选框,或者你的窗口大小和位置,或者最近的文件列表等等)。

QSettings 已经进行了相当多的优化,并且经过深思熟虑。 ini 支持很棒,除了它有时会重新排序组和键(通常按字母顺序),并且它可能会丢弃您放入其中的任何 cmets。我认为ini cmets要么以;#开头。

希望对您有所帮助。

【讨论】:

【参考方案2】:

执行此操作的一种方法是将其放入共享库中。这样你只能重新编译共享库,而不是整个项目。另一种方法是将其放入文件或数据库中并在运行时加载。

当然,您必须检查您的包含依赖项。如果你在任何地方都包含头文件,编译器将重建所有依赖它的东西,即使头文件并不是真正需要的。

【讨论】:

【参考方案3】:

另一种可能的解决方案是将所有字符串替换为 tr() 调用中的默认字符串,并使用 Qt Linguist 管理所有字符串。

您还可以在启动时从外部.qm 文件加载所有“翻译”。

【讨论】:

【参考方案4】:

这很简单:将您的可变字符串存储在 QSettings http://qt-project.org/doc/qt-4.8/qsettings.html(您可以使用 ini 文件或注册表)或 XML 文件中,这将使您的应用程序可配置。

编辑:好吧,在考虑了几分钟之后,Guilherme 的评论是正确的。 QSettings 需要以某种方式初始化(​​手动或从代码中的某些默认值)......老实说,手动编辑注册表以更改一些字符串并不是最聪明的主意。所以我得出结论,XML 或 JSON 肯定更好。它有一些优点,例如您可以保留多个配置文件,以便您在运行时切换语言等。

【讨论】:

QSettings 仍然需要将字符串放在首位才能“提取”它们。无关紧要。确实可以使用 XML 或 JSON 文件。 我不介意在应用程序启动时提取字符串。 @Vladmir 你能解释一下这可能是如何工作的吗? 我的意思是,例如你希望你的主窗口标题是可配置的。因此,您在 QSettings(ini 或注册表 - 由您决定)中有一个名为“MainWindow/Title”的条目,其中包含标题字符串,您在启动时检索它。我在答案中发布的链接中有很多示例。我特别发现“恢复 GUI 应用程序的状态”部分很有用,尽管它与字符串无关。 XML 或 JSON 肯定是一种选择,但在您的代码中需要做更多的工作。 QSettings 非常简单明了。 我编辑了我的答案以推荐 XML 或 JSON 而不是 QSettings。感谢 Guilherme 的评论。

以上是关于Qt:避免在字符串更改时重建应用程序的主要内容,如果未能解决你的问题,请参考以下文章

在web.config中更改任何内容后,是否需要重建我的解决方案?

重建应用程序时会推送令牌更改吗?

在文件更改时重建 Docker 容器

flutter_bloc 的 BlocBuilder 能否避免重建 Widget 的未更改部分?

在 Android Studio 中更改 xml 布局文件后需要重建

为啥在构建后源代码的更改并不总是反映在机器代码中而重建工作?