![73b6276561d9840c4fe1571e7d96c21a.png](https://img-blog.csdnimg.cn/img_convert/73b6276561d9840c4fe1571e7d96c21a.png)
文章首发公众号:Qt那些事儿
序
UI文件为标准的XML h文件为标准的Qt语法的文件。 先思考一分钟:如何让你来设计,你如何做转化?
过程
其实过程很简单 读取ui文件(即xml) -> 经过一些规则的变化-> 输出.h文件
实际上 只是单纯的规则变化 - 字符串变化,这个姑且认为是词法分析的一个简单版本吧。(应该算应该算
Qt代码以及位置
Qt对应的工程名字为UIC
代码位置
C:QtQt5.14.15.14.1Srcqtbasesrctoolsuic
是一个简单的pro文件,可以直接用QtCreator打开
配置
如果平时有注意Qt的文件编译的时候会发现uic的编译过程的。建议有时间多观察下Qt代码的编译过程,对比C++的编译过程
举个栗子
我们把 form.ui 转化成 ui_form.h 需要在工程配置中 在Command line arguments里把对应的命令加上 可以看下我的配置
![3ea7ce54fb15788cac2de752b8c03dc0.png](https://img-blog.csdnimg.cn/img_convert/3ea7ce54fb15788cac2de752b8c03dc0.png)
格式就是 源文件(.ui) -o 目标文件(.h)
然后可以直接点击调试来调试Qt的uic的源码了。
forn.ui
这里先贴上form.ui的描述
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>wpsObject</class>
<widget class="QWidget" name="wpsObject">
<property name="windowModality">
<enum>Qt::ApplicationModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>481</width>
<height>394</height>
</rect>
</property>
<property name="windowTitle">
<string>wpsTitle</string>
</property>
</widget>
<resources/>
<connections/>
</ui>
解析过程
比如如何解析UI文件中的widget的一部分信息的代码
<widget class="QWidget" name="wpsObject">
<property name="windowModality">
<enum>Qt::ApplicationModal</enum>
</property>
代码在
C:QtQt5.14.15.14.1Srcqtbasesrctoolsuicui4.cpp
中的
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("author"), Qt::CaseInsensitive)) {
setElementAuthor(reader.readElementText());
continue;
}
if (!tag.compare(QLatin1String("comment"), Qt::CaseInsensitive)) {
setElementComment(reader.readElementText());
continue;
}
if (!tag.compare(QLatin1String("exportmacro"), Qt::CaseInsensitive)) {
setElementExportMacro(reader.readElementText());
continue;
}
if (!tag.compare(QLatin1String("class"), Qt::CaseInsensitive)) {
setElementClass(reader.readElementText());
continue;
}
if (!tag.compare(QLatin1String("widget"), Qt::CaseInsensitive)) {
auto *v = new DomWidget();
v->read(reader);
setElementWidget(v);
continue;
}
重点是解析widget这句,这是解析XML中Widget字段相关的属性信息的
if (!tag.compare(QLatin1String("widget"), Qt::CaseInsensitive)) {
auto *v = new DomWidget();
v->read(reader);
setElementWidget(v);
continue;
}
看里面DomWidget
的实现
while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("class"), Qt::CaseInsensitive)) {
m_class.append(reader.readElementText());
continue;
}
if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
if (!tag.compare(QLatin1String("script"), Qt::CaseInsensitive)) {
qWarning("Omitting deprecated element <script>.");
reader.skipCurrentElement();
continue;
}
if (!tag.compare(QLatin1String("widgetdata"), Qt::CaseInsensitive)) {
qWarning("Omitting deprecated element <widgetdata>.");
reader.skipCurrentElement();
continue;
}
if (!tag.compare(QLatin1String("attribute"), Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
m_attribute.append(v);
continue;
}
重点是这一句,这一局开始解析 property的内容
if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
auto *v = new DomProperty();
v->read(reader);
m_attribute.append(v);
continue;
}
回头再看看我们要解析的ui文件的那部分,xml的property信息就在这里。
<widget class="QWidget" name="wpsObject">
<property name="windowModality">
<enum>Qt::ApplicationModal</enum>
</property>
widget中的property元素就是在这里解析的。
是不是超级简单???!!!!
总结
这部分代码个人觉得连编译过程中的语法解析都算不上。只是按照规则,将XML转化成了CPP语法的文件。好吧,听起来也算是语法解析。不过这次算是我们肉眼能够看到的。