在使用Qt5.8完成程序动态语言切换时遇到的问题

因为之前了解过一些Qt国际化的东西,所以在写程序的时候需要显示给用户的字符都使用了 tr(" ")的形式,然后使用 Qt Linguist得到相应的 qm(Qt message)文件,再通过网上介绍的方式,在 main函数中使用 installTranslator,即可让程序在启动时自动判断语言环境,加载相应语言。

至此,静态语言切换已经完成,下面要做的是动态切换(即不需要重启软件)。

1.首先,令语言能够切换的 GUI组件用的是 QComboBox,信号是 currentIndexChanged,在于这个信号对应的槽中加载不同的语言文件,安装 translator,并且调用主界面的retranslateUI函数。这样,每当下拉框的选中项发生改变时,语言就会立即切换,而不是像大多数软件一样需要再次点击“确定”后才会切换。但是这么做出现了问题,因为如果是使用 Qt Designer生成的界面,在自动生成的 retranslateUI程序(ui_**.h文件)中,会先调用 QComboBox类的 clear,再调用 insertItems函数,而这两个函数都会触发 currentIndexChanged信号。这样的话,就会产生一个死循环。

2.后来改成了点击“确定”后才会切换语言,这样也不需要再使用 QComboBox类的 currentIndexChanged信号,也就避开了上面的死循环。

3.只调用  retranslateUI函数时,则只有在 Qt Designer中输入的字符能够成功翻译。后来上网看别人的 Blog后知道,自己在代码中赋值的字符需要统一放到一个函数(retranslate)中,在安装好 translator后再调用这个函数。这样来看,Qt实现国际化的原理大致是,在显示字符时,会先从当前 translator中寻找该字符的翻译文本,有的话显示“翻译文本”,没有则显示“原本字符”。所以,由于一开始写程序时用的就是英文,英文的语言文本可以不做翻译,直接由 ts文件发布为 qm文件。

4.别人的 Blog中还写到:因为当调用 installTranslator后,会向所有的类发送一个 LanguageChanged事件。如果要实时切换另一个窗口的语言,就需要在另一个窗口类中重载 changeEvent,并判断事件是否是 LanguageChanged类型,是的话调用它的 retranslateUI函数,如果有字符是在代码中给出的,还需要自定义一个 retranslate函数,然后再调用这个函数。

5.一开始在自定义的 retranslate函数中,直接使用  setText(QApplication::translate("Mainwindow", "str", 0, QApplication::UnicodeUTF8));  形式,报错。当前 Qt版本(5.8)下,则需要使用 setText(QApplication::translate("Mainwindow", "str",Q_NULLPTR)); 形式。

6.这样的话,每一个组件有两处字符串赋值的地方,不利于修改。我就想着可不可以只保留一处呢?看到 ui_**.h文件中的初始化函数中就会调用 retranslateUI函数,我就想着构造函数中就不对字符串赋值了,而都放到自定义的 retranslate函数中,在 Mainwindow的构造函数中调用 retranslate函数即可。可是这样 Qt Linguist就找不到这些需要翻译的字符了,然后在别人的代码中看到使用的是 setText(tr("---")); 形式。这样,就也能找到这些需要翻译的字符了。

7.但是出了一个很奇怪的问题,一开始是英文,英->中->英切换就没问题;一开始是中文的话,就切换不成英文。不知怎的,我就想到把程序启动时自动加载相应语言的代码改到 MainWindow的构造函数中,结果就好了。。。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏H2Cloud

C++中消息自动派发之二 About IDL解析器

  前一篇blog中讲了如何在C++中实现消息的自动派发,而关键点在于如何实现通过IDL文件自动生成msg_dispatcher模板类。有几个网友提醒我idl解...

4059
来自专栏AI深度学习求索

AI实践:如何应用多进程Multiprocessing编程?

多核 multiprocessing:现在计算机都有多核处理器,将任务分给多个核来处理,他们有单独的运算空间和计算能力,避免了多线程的劣势。

1272
来自专栏linux、Python学习

十分钟带你了解 Python3 多线程核心知识

每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

2210
来自专栏JavaQ

Java多线程编程笔记之Condition

本篇内容基于JDK7,涉及Condition常用方法。 1.概述 Condition接口位于java.util.concurrent.locks包下,实现类有 ...

2765
来自专栏Java编程技术

Dubbo剖析-增强SPI的实现

在Duboo剖析-整体架构分析中介绍了dubbo中除了Service 和 Config 层为 API外,其他各层均为SPI,为SPI意味着下面各层都是组件化可以...

1411
来自专栏noteless

javaweb请求编码 url编码 响应编码 乱码问题 post编码 get请求编码 中文乱码问题 GET POST参数乱码问题 url乱码问题 get post请求乱码 字符编码

然后使用      65------>$ 另外一种解码方式解读,显然A就变成了$,这不就是乱码了么

1893
来自专栏大闲人柴毛毛

Java并发编程的艺术(三)——volatile

1. 并发编程的两个关键问题 并发是让多个线程同时执行,若线程之间是独立的,那并发实现起来很简单,各自执行各自的就行;但往往多条线程之间需要共享数据,此时在并...

4397
来自专栏流柯技术学院

Loadrunner中web_find和web_reg_find函数的使用与区别

总结一下Loadrunner中的检查点函数,主要介绍两个函数:web_find()和web_reg_find();这两个函数均用于内容的查找,但两者也有本质的区...

2072
来自专栏杂七杂八

列表、字典、集合中筛选数据

传统迭代法 data = [1,5,-3,-2,8,0,9] res = [] for x in data: if x >=0: res...

3796
来自专栏向治洪

命令模式

命令模式定义 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。 作用 命令模式主要应用于将行...

2019

扫码关注云+社区

领取腾讯云代金券