2.2 加入主程序
目前,已经编写了登录对话框类的头文件及其实现代码,现在把它加入到主程序中编译运行。
// chapter02/mydialog/src/mydialog.cpp. #include <QtGui/QtGui> #include "logindlg.h" int main(int argc, char* argv[]) { QApplication app(argc, argv); QTextCodec::setCodecForTr(QTextCodec::codecForName("gb18030")); QTranslator translator; { QStringList environment = QProcess::systemEnvironment(); QString str; bool bFinded = false;
QTranslator类提供了对文本输出的国际化(internationalization)的支持。创建的QTranslator对象translator包含了一组从源语言到目标语言的翻译(translations),这些翻译是通过QTranslator对象参照Qt翻译文件来实现的。关于国际化的详细内容,请参阅本书第21章“国际化”。
静态函数QProcess::systemEnvironment()获取进程的环境变量,并将其存放在QStringList对象environment中。QStringList类是存放Qt字符串QString对象的列表类。
接下来,定义一个存放环境变量“QTDIR”的Qt字符串QString对象str;定义查找结果的标识符bFinded,如果找到环境变量“QTDIR”其值为true,否则为false,bFinded初始化为false(变量的初始化是一个良好的编程习惯)。
foreach(str, environment) { if(str.startsWith("QTDIR=")) { bFinded = true; break; } }
foreach()函数体的功能是在获取的环境变量列表中查找以“QTDIR=”开头的字符串,即查找环境变量“QTDIR”。如果找到环境变量“QTDIR”,则将其保存在QString对象str中,并设置标识符bFineded为true,然后退出循环;否则继续进行查找,直到遍历完整个environment环境变量列表。
foreach ( variable, container )是Qt定义的一个宏,它的作用是遍历QList容器类变量container并依次把列表项存放在变量variable中。此外,Qt还提供了功能等价的宏变量Q_FOREACH (variable, container),不同的是foreach()宏变量是可以通过配置qmake工程文件屏蔽掉的(CONFIG +=no_keywords),而Q_FOREACH()却总是可以用。
if(bFinded) { str = str.mid(6); bFinded = translator.load("qt_" + QLocale::system().name(), str.append("/translations/")); if(bFinded) qApp->installTranslator(&translator); else qDebug() << QObject::tr("没有支持中文的Qt国际化翻译文件!"); } else { qDebug() << QObject::tr(" 必须设置QTDIR环境变量!"); exit(1); } }
这段代码的功能是给应用程序安装翻译器(translator)。
if()语句首先判断是否已经查找到环境变量“QTDIR”。如果存在环境变量“QTDIR”,则通过QString::mid()函数取得环境变量的值(去掉字符串“QTDIR=”后剩下的内容),即Qt的安装路径。
函数QTranslator::load(const QString& filename, const QString& directory = QString(), const QString& search_delimiters = QString(), const QString& suffix = QString())加载Qt的翻译文件(translation file):
● 形参filename+形参suffix(如果没有指定suffix的实参,则suffix使用默认值“.qm”)指定加载的文件名称。
● 形参directory指定加载的路径。
● 形参search_delimiters指定翻译文件名字的过滤器(如果search_delimiters为空,其默认值为“_.”)。
函数QLocale::system().name() 以“语言_国家”的形式返回系统场景(system locale,安装Linux操作系统的时候已经确定了系统的场景)的名字(“语言”表示为两个小写字母的IOS639语言代码,简体中文的语言代码为zh;“国家”表示为两个大写字母的ISO3166国家代码,中国的国家代码为CN)。因此,在登录对话框应用程序中,相当于调用了
QTranslator::load("qt_zh_CN" , "$QTDIR/translations/");
该函数将以下列流程加载Qt翻译文件(在参数directory指定的目录下):
(1)查找具有后缀suffix(.qm)文件名的文件,即查找qt_zh_CN.qm;
(2)如果文件qt_zh_CN.qm不存在,查找没有后缀suffix(.qm)文件名的文件,即查找qt_zh_CN;
(3)如果文件qt_zh_CN不存在,查找search_delimiters(因为没有指定search_delimiters的实参,所以search_delimiters值为默认值“_”)定界符之前的字符加后缀suffix构成文件名的文件,即查找qt_zh.qm;
(4)如果文件qt_zh.qm不存在,查找没有后缀suffix(.qm)文件名的文件,即查找qt_zh。
(5)重复步骤(3)和(4),即查找qt.qm和qt。
在上述过程中,如果QTranslator::load() 函数加载成功,返回true;否则返回false。事实上,应用程序的翻译器在步骤1就已经查找到了Qt翻译文件qt_zh_CN.qm(文件位置在Qt安装路径的translations目录下,如D:\Qt\4.7.0\translations),并成功地进行了加载。
函数QApplication::installTranslator()为应用程序添加翻译文件(通过翻译器指定的翻译文件)。一个应用程序可以添加多个翻译文件,当应用程序需要进行翻译的时候,按照“后添加先使用”的原则依次在翻译文件中搜索需要的翻译文本,一旦找到一个匹配的翻译文件应用程序就停止进行搜索。
程序中,使用了大括号把加载/安装翻译文件的代码括了起来,这样做是为了及时销毁以后不再使用的栈对象,这在大型的应用程序开发中是有必要的。
CLoginDlg dlg; return dlg.exec(); }
创建一个CLoginDlg对话框的栈对象dlg。
槽函数QDialog::exec()以模态方式显示对话框对象dlg,并进入对话框对象dlg的事件循环。当登录对话框运行完毕后将返回它的运行结果。注意,此处并没有启动Qt应用程序QApplication对象的事件循环,尽管也定义了一个QApplication对象app(Qt GUI应用程序必须有且仅有一个QApplication对象)。
扩展阅读
对话框分为两种类型:
● 模态(modal)对话框;
● 非模态(modeless)对话框。
模态对话框类型是最普遍的对话框类型。模态对话框在没有消失之前用户不能与同一个应用程序的其他窗口进行交互,直到该对话框关闭。对于非模态对话框,当被打开时,用户既可以选择与该对话框进行交互,也可以选择与应用程序的其他窗口进行交互。
非模态对话框如果是栈对象,当代码退出对话框对象的作用域后,该对话框就自动销毁了,这就造成用户来不及和对话框进行交互,对话框就消失了。因此,必须通过new操作在堆中创建非模态对话框。
Qt中,QDialog::exec()以模态方式显示对话框,而QDialog::show()默认以非模态方式显示对话框。
最后,编译、连接登录对话框应用程序。程序的运行界面如图2-13和图2-14所示。
图2-13 输入用户名和密码
图2-14 用户名和密码的验证