一 。没有使用general form 和 使用 general form 后,file层面和代码层面的不同比较
file层面的不同
代码层面的不同,
在 使用了general form之后,在主界面的构造方法中,使用ui->setupUi(this),就完成了所有UI的处理。
而之前我们的没有使用general form的时候,需要自己通过写代码一步一步的完成。
比较多出来的file 以及 代码层面的不同 后的 疑问:
在没有使用general form时,我们的代码生成是使用了一系列函数生成的,那么是不是 ui->setupUi(this);的内部也是和我们使用一系列函数差不多呢?
验证:
1.我们先来看多出来的mainwindow.ui是个啥?
在QT Creator中双击 mainwindow.ui,看到会跳转到一个可以操作的UI界面
使用 UE 打开 mainwindow.ui,可以看到是一个xml格式的文件
结论:mainwindow.ui是一个xml的文件。该文件中用xml格式记录了当前mainwindow中的组件。QT Creator在打开这个xml的时候,做了事情,将xml文件变成了可视化的UI。如果我们通过可视化UI,给里面的增添改UI,然后QT Creator会将我们的操作变成xml文件。
验证QT Creator 将开发者可视化UI的操作变成xml实验:
之前界面和xml是这样:
我们往界面上通过可视化UI 添加一个 qpushbutton,保存后,可以看到xml文件多了一些东西
2. 那么这个 ui->setupUi(this)是干啥的呢?
我们按照以往的经验,在 ui->setupUi(this) 这一行上,按住ctrl+鼠标左键,看一下这一行代码跳转到哪里?--结果跳出来error,
这个error的意思是:我们找不到ui_mainwindows.h这个文件。或者没有权限打开这个文件。该文件是在这个目录下:
D:\code_qt\build-004qtUIstudy-Desktop_Qt_5_14_2_MinGW_32_bit-Debug\ui_mainwindow.h
那我们在磁盘里面找一下这个文件。发现确实没有这个文件。
我们再来看一下给出的error信息 路径是在
D:\code_qt\build-004qtUIstudy-Desktop_Qt_5_14_2_MinGW_32_bit-Debug\ui_mainwindow.h
这时候就想到了,这个应该是 项目build 之后生成的吧,于是查看了一下该项目的配置,果然是在D:\code_qt\build-004qtUIstudy-Desktop_Qt_5_14_2_MinGW_32_bit-Debug下面,也就是我们需要构建之后,才会生成 ui_mainwindow.h这个文件。
构建此项目
构建完成后,发现就生成了这个目录了。
在QT Creator 中 打开ui_mainwindow.h文件查看,还是ctrl+鼠标左键打开。为什么不用UE直接打开呢?因为在 QT Creator 中打开代码有关联性,方便查看。我们终于看到了熟悉的画面,和我们不使用general form时候的代码。
二 使用general form 后,QT 帮我们到底做了什么 的回答
1.QT Creator 提供了可视化的UI,方便开发者增删改UI,
2.改动的UI,QTCreator 会变成本质上是xml的 xxx.ui文件
3.然后QT 会在build 的过程中,将 xxx.ui文件变成ui_xxx.h文件。而这个 ui_xxx.h 文件并不是.h文件,实际上也含有.cpp的内容。
总结
通过QT build 的过程
xxx.ui--------------------------------------> 变成 最终的 ui_xxx.h 文件
在代码中 通过 ui->setupUi(this); 这一行代码 加载 ui_xxx.h,完成 UI的创建。
好处1:
开发者可以通过可视化UI ,实现自己想要的UI界面。QT 帮忙转换成代码,最终通过ui->setupUi(this)加载这些代码生成UI。
好处2:
开发者可以通过 查看这些可视化UI的最终代码,学习在代码层面实现,而不是借助可视化UI工具。
另一个问题:既然QT给了我们可视化UI的界面,为什么还要在第一章学习用代码生成UI呢?这是因为两个原因:1是在实际工作用,用代码生成UI的部分也不少。作为开发者首先就要要弄清楚这个原理。2是因为我们在后面学习到深度定制某一个UI控件的时候(假设我们这里的需求是自己开发一个button,自己的这个button 不能接受鼠标的点击事件,),这就需要我们自己create mybutton,并重写 mybutton的click事件,或者直接屏蔽click事件,这些的基础都是自己创建UI并。如果这块暂时想不明白也没有关系,学到后面知识就了解了。
三。 QT控件学习
实际上就是学习如下图的所有,但是有些UI不常用,有些UI,常用的部分,会在标题前面加上红色的"常用"两个字
四 ,Layouts 部分详解
1.垂直布局Vertical Layout 对应类为(QVBoxLayout)
学习思路是这样的,我们先在UI上拖拽一个 Vertical Layout 进去,然后给 Vertical Layout里面加上两个button。弄好UI后,保存一下,然后 使用 QT 的 "构建",最后看QT 生成的源码 ui_xxx.h
结合源码 和 QT api助手,学习垂直布局的常用写法,以及参数。
1.1拖入UI后的效果
1.2 构建
1.3 结合 QT-API助手 和 QT生成代码 学习
代码位置ui_mainwindow.h
D:\code_qt\build-004qtUIstudy-Desktop_Qt_5_14_2_MinGW_32_bit-Debug\ui_mainwindow.h
全部代码:
/********************************************************************************
** Form generated from reading UI file 'mainwindow.ui'
**
** Created by: Qt User Interface Compiler version 5.14.2
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/#ifndef UI_MAINWINDOW_H
#define UI_MAINWINDOW_H#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>QT_BEGIN_NAMESPACEclass Ui_MainWindow
{
public:QAction *actionsave;QWidget *centralwidget;QWidget *verticalLayoutWidget;QVBoxLayout *verticalLayout;QPushButton *pushButton;QPushButton *pushButton_2;QMenuBar *menubar;QStatusBar *statusbar;void setupUi(QMainWindow *MainWindow){if (MainWindow->objectName().isEmpty())MainWindow->setObjectName(QString::fromUtf8("MainWindow"));MainWindow->resize(888, 666);actionsave = new QAction(MainWindow);actionsave->setObjectName(QString::fromUtf8("actionsave"));centralwidget = new QWidget(MainWindow);centralwidget->setObjectName(QString::fromUtf8("centralwidget"));verticalLayoutWidget = new QWidget(centralwidget);verticalLayoutWidget->setObjectName(QString::fromUtf8("verticalLayoutWidget"));verticalLayoutWidget->setGeometry(QRect(70, 60, 241, 191));verticalLayout = new QVBoxLayout(verticalLayoutWidget);verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));verticalLayout->setContentsMargins(0, 0, 0, 0);pushButton = new QPushButton(verticalLayoutWidget);pushButton->setObjectName(QString::fromUtf8("pushButton"));verticalLayout->addWidget(pushButton);pushButton_2 = new QPushButton(verticalLayoutWidget);pushButton_2->setObjectName(QString::fromUtf8("pushButton_2"));verticalLayout->addWidget(pushButton_2);MainWindow->setCentralWidget(centralwidget);menubar = new QMenuBar(MainWindow);menubar->setObjectName(QString::fromUtf8("menubar"));menubar->setGeometry(QRect(0, 0, 888, 21));MainWindow->setMenuBar(menubar);statusbar = new QStatusBar(MainWindow);statusbar->setObjectName(QString::fromUtf8("statusbar"));MainWindow->setStatusBar(statusbar);retranslateUi(MainWindow);QMetaObject::connectSlotsByName(MainWindow);} // setupUivoid retranslateUi(QMainWindow *MainWindow){MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "MainWindow", nullptr));actionsave->setText(QCoreApplication::translate("MainWindow", "save", nullptr));pushButton->setText(QCoreApplication::translate("MainWindow", "\346\214\211\351\222\2561", nullptr));pushButton_2->setText(QCoreApplication::translate("MainWindow", "\346\214\211\351\222\2562", nullptr));} // retranslateUi};namespace Ui {class MainWindow: public Ui_MainWindow {};
} // namespace UiQT_END_NAMESPACE#endif // UI_MAINWINDOW_H
关键代码:
结论(重点):
1.我们拖拽的垂直布局Vertical Layout 实际上会做两件事情
第一,生成一个新widget,该新的widget 的主控件是 centralwidget。
第二,然后基于这个新的widget创建QVBoxLayout
2. 最后的两个button 也是基于 新widget 创建的。
也就是说,button的生命周期依存于 新的widget
3. 但是UI上的显示在layout上 --------通过 layout->addwidget(pushbutton) 实现。
4.layout在构造方法中的第一个参数,表示了这个layout是那个widget的layout。
除了这个构造方法外,QT api 助手中给了setLayout方法
QWidget *window = new QWidget;QPushButton *button1 = new QPushButton("One");QPushButton *button2 = new QPushButton("Two");QPushButton *button3 = new QPushButton("Three");QPushButton *button4 = new QPushButton("Four");QPushButton *button5 = new QPushButton("Five");QHBoxLayout *layout = new QHBoxLayout;layout->addWidget(button1);layout->addWidget(button2);layout->addWidget(button3);layout->addWidget(button4);layout->addWidget(button5);window->setLayout(layout);window->show();
1.4 自己写代码验证。
这里创建一个 QT设计师界面类,写代码完成我们的代码验证
这里选择main window 和 widget其实都是可以的,反正都是学习用的
在main.cpp中调用的时候,改动代码如下:新建一个StudyMainWindow实例,然后show。
也就是说:我们在main函数中显示自己写的 studymainwindow。
int main(int argc, char *argv[])
{QApplication a(argc, argv);
// MainWindow w;
// w.show();StudyMainWindow sm;sm.show();return a.exec();
}
在studymainwindow.ui中什么也不干。
然后在studymainwindow 的构造函数中写代码 模拟前面我们在UI中的Vertical Layout的写法,这样就能验证之前的想法了。
也就是说:当前代码中是通过如下的方法加载UI的:
1.StudyMainWindow的构造方法中通过 ui->setupUi(this);加载一部分UI
2.StudyMainWindow的构造方法中ui->setupUi(this)方法后,通过自己写的代码加载一部分UI
先来看一下 ui->setupUi(this);中干了啥?
弄了一个QMenuBar,弄了一个QWidget(该widget就是centralwidget),弄了一个QStatusBar
StudyMainWindow->resize(800, 600);menubar = new QMenuBar(StudyMainWindow);menubar->setObjectName(QString::fromUtf8("menubar"));StudyMainWindow->setMenuBar(menubar);centralwidget = new QWidget(StudyMainWindow);centralwidget->setObjectName(QString::fromUtf8("centralwidget"));StudyMainWindow->setCentralWidget(centralwidget);statusbar = new QStatusBar(StudyMainWindow);statusbar->setObjectName(QString::fromUtf8("statusbar"));StudyMainWindow->setStatusBar(statusbar);
自己写的代码如下:
StudyMainWindow::StudyMainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::StudyMainWindow)
{ui->setupUi(this);//在 ui->setupUi(this)后,我们写自己想要验证部分的代码//1.创建新的widget,注意这里给定参数是 ui中的centralwidget。那么这个newwidget的大小就和centralwidget的大小一致了//1.1 我们打印一下 ui->centralwidget 的大小,打印结果是 width = 100, height = 30,从studymainwindows.ui上来看,我们并没有主动的设置centralwidget的大小/*那么谁设定的呢?进而查看了 QT帮我们生成的ui_mainstudymainwindow.h文件里面的写法,也只有如下的两句centralwidget = new QWidget(StudyMainWindow);centralwidget->setObjectName(QString::fromUtf8("centralwidget"));那么怀疑的对象只能是在QWidget.cpp中做了设置大小的事情,于是查看qwiget.cpp,发现如下代码大约在qwidget.cpp 的1046行data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,640,480);也就是说,你new 的qwidget,如果有父控件,则默认给100,30的大小,如果没有父控件,则给出640,480的控件这意味着啥?默认mainwindow的 主控件centralwidget的大小就是100,30的大小的,如需要,可以自己改动。*/qDebug()<<this->ui->centralwidget->width(); //这个值是100qDebug()<<this->ui->centralwidget->height();//这个值是30QWidget *newwidget = new QWidget(ui->centralwidget);//由于centralwidget是100,30的,那么newwidget应该也newwidget->setGeometry(0,0,500,600);//new 一个 QVBoxLayout出来,参数为刚才创建的newwidget,这样 QVBoxLayout 就是newwidget的layout,如果不设置参数,则要通过 newwidget.setLayout(vlayout) 方法设置的newwidget的layout就是vlayout.QVBoxLayout *vlayout = new QVBoxLayout(newwidget);QPushButton *button1 = new QPushButton(newwidget);button1->setText("aaa");QPushButton *button2 = new QPushButton(newwidget);button2->setText("bbb");vlayout->addWidget(button1);vlayout->addWidget(button2);
}
创建layout的时候如果不加参数的写法
StudyMainWindow::StudyMainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::StudyMainWindow)
{ui->setupUi(this);QWidget *newwidget = new QWidget(ui->centralwidget);newwidget->setGeometry(0,0,500,600);QHBoxLayout *hlayout = new QHBoxLayout();QPushButton *button1 = new QPushButton();button1->setText("ccc");QPushButton *button2 = new QPushButton();button2->setText("ddd");hlayout->addWidget(button1);hlayout->addWidget(button2);newwidget->setLayout(hlayout);}
1.5 Vertical Layout其他属性和UI对照图,以及代码的写法
我们弄一个 Vertical Layout,然后给 Vertical Layout中加两个button。
思路是这样的:改一下红色框框的属性,看看改动后 在UI层面的显示,以及生成的代码主要使用的api,然后再结合 QT api 助手学习
1.5.0. layoutName:控件的名称
1.5.1 改动layoutLeftMargin,layoutTopMargin,layoutLeftMargin,layoutBottomMargin
layoutLeftMargin:控件的左边距;比如我们设置这个值为20,可以看到内部的button距离左侧的边距有了变化UI
QT生成的代码:
verticalLayout->setContentsMargins(20, 40, 60, 80);
QT api 助手中的api 说明:
void QLayout::setContentsMargins(int left, int top, int right, int bottom)
Sets the left, top, right, and bottom margins to use around the layout.
By default, QLayout uses the values provided by the style. On most platforms, the margin is 11 pixels in all directions.
This function was introduced in Qt 4.3.
1.5.2 改动layoutspacing的值-layoutSpacing:控件间的间距,效果如图
UI
QT生成的代码:
verticalLayout->setSpacing(70);
QT api 助手中的api 说明:
void QBoxLayout::setSpacing(int spacing)
Reimplements QLayout::setSpacing(). Sets the spacing property to spacing.
1.5.3 layoutStretch:控制各个控件所占的比例,列表中的每个整数表示对应控件的伸缩因子,列表长度应与布局中的控件数量相等,伸缩因子越大,控件在布局中所占的空间就越大,但是在QBoxLayout中好像不起作用。
1.5.4 layoutSizeConstraint:控件在适应不同布局大小时,子控件的大小和位置如何变化
- SetDefaultConstraint:使用默认的尺寸,布局没有特定的约束
- SetNoConstraint:布局没有特定的尺寸策略,保持用户设定的已有属性
- SetMinimumSize:布局和其子控件的尺寸至少为设定的最小值,可以随着窗口的增大而增大
- SetFixedSize:控件大小为固定值,不会随着布局大小的变化而变化
- SetMaximumSize:限制控件的最大尺寸,可以随着窗口缩小而缩小
- SetMinAndMaxSize:布局和其子控件的尺寸被限制在设定的最小值和最大值之间
2.水平布局Horizontal Layout 对应类为(QHBoxLayout)
3.网络布局Grid Layout 对应类为 (QGridLayout)
4.表格布局Form Layout 对应类为 (QFormLayout)
五. spacers部分详解
Qt6教程之二(2) Spacers_qt spacer-CSDN博客