关于Qt的UI的一点理解
许久不用Qt,突然对Qt的UI编程模式有些不解,概念上有些混乱,一番查找之后,基本又搞明白了,记录一下。
使用Qt Designer可以可视化布局你的窗体和组件,这个布局文件可以直接生成一个UI类,供控件使用。但是在代码中,见到一句ui.setupUi(this),让我疑惑了,究竟最终弹出的窗口是这个UI类,还是QWidget或QMainWindow,这个setupUi又是干什么的,从参数看是把两者绑定了一起。
通过代码,我们看看一个普通的窗体包含哪些东西,QWidget示例,看头文件
class qtdemo : public QWidget
{
Q_OBJECT
public:
qtdemo(QWidget *parent = Q_NULLPTR);
private:
Ui::qtdemoClass ui;
};
1)一个用户定义的qtdemo类,继承于QWidget
2)qtdemo中,含有一个UI文件生成的对象实例Ui::qtdemoClass ui
从这里,我们可以想到我们的控件对象是通过包含一个UI对象来访问控制我们在布局文件中添加的组件资源的,比如在Qt Designer中,为布局加一个按钮对象,可以在qtdemo中,以如下方式访问,达到禁用按钮的效果
qtdemo::qtdemo(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
ui.pushButton->setEnabled(false);
}
从这里,我们可能会想,UI对象包含按钮组件,qtdemo是主窗口本身,他俩是协作关系,那如果不setupUi又会怎样呢?从生成的setupUi源码可以更好的理解他们之间的关系,上述说法还是有问题的。
void setupUi(QWidget *qtdemoClass)
{
if (qtdemoClass->objectName().isEmpty())
qtdemoClass->setObjectName(QStringLiteral("qtdemoClass"));
qtdemoClass->resize(600, 400);
pushButton = new QPushButton(qtdemoClass);
pushButton->setObjectName(QStringLiteral("pushButton"));
pushButton->setGeometry(QRect(110, 140, 75, 23));
retranslateUi(qtdemoClass);
QMetaObject::connectSlotsByName(qtdemoClass);
} // setupUi
看UI对象setupUi的实现,我们发现虽然UI对象包含了一个pushButton对象指针,但真正生成按钮并进行相关设置却是在setupUi中,且引用了qtdemo作为父对象。即是说,其实这个pushButton是属于qtdemo的,那为什么要走UI中控制生成和设置呢?这个就是UI的真正作用了。
UI是一个布局对象,他是用来控制界面布局和组件分配的,但UI对象本身并不是,也不包含任何窗体实体(包括在UI上面布局的控件实体),他只是控制使用他的窗体及其控件的行为表现,类似于为窗体定制了一件衣服,但是要做这件衣服,穿这件衣服,还是要一个人实体参与进来才行。
这样的话,所有关于界面的元素、配置、布局,便从主体中抽离出来,任何窗体对象想使用这样的UI,包含一个UI对象实例,然后setupUi一下,把自己传进去就好了。
所以,setupUi的本质,便可以理解为真正实例化UI对象的过程。