知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。
还整了一个如何相互之间调用函数的文章,感兴趣可以看:【Visual Studio】Qt 在其他 cpp 文件中调用主工程下文件中的函数。
文章目录
主界面工程为
A
,添加的文件名字为
test
,目标是在
test
文件里操作
A
工程里的
ui
控件。
简洁版直接看这个截图就行,大意就是将老的实例化
ui
变成指针,将地址传递给
p_ui
,然后通过调用
p_ui
来间接调用
ui
。
名称解释:
c_test
表示新建的类p_ui
表示新建的类里的指针类型的成员变量testFun()
表示新建的类的函数mc_test
实例化的类,用来调用新建的c_test
的类
详细版可以看下边这些。
创建一个原始工程名字为
A
为了更好地演示,首先创建一个原始工程,名字为
A
,并打印一段文字。效果如下图所示:
工程的四个项目文件分别如下:
A.ui
A.h
// A.h#pragmaonce#include<QtWidgets/QMainWindow>#include"ui_A.h"classA:publicQMainWindow{
Q_OBJECT
public:A(QWidget *parent =nullptr);~A();private:
Ui::AClass ui;};
类定义:
class A : public QMainWindow
指示
A
类是一个继承自 Qt 的主窗口类
QMainWindow
的类。通过继承,
A
类获得了
QMainWindow
的功能,并可以在其基础上进行扩展。
Q_OBJECT
: 这是一个宏,用于启用 Qt 的元对象系统(Meta-Object System,MOC)。元对象系统是 Qt 中一种用于实现信号与槽机制,反射和其他元编程功能的机制。为了使用这些功能,类必须包含 Q_OBJECT 宏。
构造函数:
A(QWidget *parent = nullptr);
是
A
类的构造函数。构造函数在创建类的实例时被调用。它的参数
QWidget *parent
表示构造函数的父类,这里设置为
nullptr
,表示没有父类。
析构函数:
~A();
是
A
类的析构函数。析构函数在类的实例被销毁时被调用。在析构函数中,通常进行资源的释放和清理工作。
私有成员变量:
Ui::AClass ui;
是一个私有成员变量,它是通过
UI
文件自动生成的用户界面类的实例。通过这个变量,您可以访问和操作
UI
文件中定义的组件和布局。
双冒号
::
表示作用域解析运算符(Scope Resolution Operator)。它有两个主要的用途:
- 命名空间成员的访问:在 C++ 中,可以使用命名空间将一组相关的类、函数、变量等封装在一起。双冒号
::
用于访问命名空间中的成员。在代码中,Ui::AClass
中的Ui
表示一个命名空间,AClass
则是在Ui
命名空间中定义的一个类。因此,Ui::AClass
表示访问位于Ui
命名空间中的AClass
类。- 静态成员的访问:在类中,可以定义静态成员(Static Members),这些成员属于类本身,而不是类的实例。双冒号
::
用于访问类的静态成员。在代码中,Ui::AClass
中的Ui
表示一个命名空间或类,而AClass
则是在这个命名空间或类中定义的一个静态成员。因此,Ui::AClass
表示访问类Ui
中的静态成员AClass
。在上述代码中,
Ui::AClass
表示访问命名空间或类
Ui
中的类
AClass
。这个类是通过
Qt
设计师生成的,用于描述与窗体
A
相关联的用户界面。
总结来说,双冒号
::
用于在 C++ 中访问命名空间中的成员或类的静态成员,帮助准确定位所需的符号,避免命名冲突,并使代码更加清晰和模块化。
Ui::AClass
表示一个名为
AClass
的用户界面类。它是通过 Qt 的用户界面设计器创建的类,用于描述窗体的布局和组件。通常,当你使用 Qt 设计师(Qt Designer)创建一个用户界面时,它会生成一个对应的头文件(通常以
.h
为扩展名),其中包含了一个名为
Ui::ClassName
的类。
ClassName
是你在设计师中指定的窗体的类名,可以是你创建的窗体的名称或其他自定义名称。在上述示例代码中,
Ui::AClass
表示在 Qt 设计师中创建的与窗体
A
相关联的用户界面类。它描述了
A
窗体的布局和组件,包括在设计师中创建的各种控件(如按钮、标签、文本框等)的属性和布局信息。
#include"ui_A.h"
Ui::AClass
是通过包含名为
ui_A.h
的头文件来定义的。在这个头文件中,Qt 设计师自动生成了与
A
窗体相关的用户界面类的声明和定义。通过包含
ui_A.h
头文件,你可以在
A
类中创建一个名为
ui
的对象,它是
Ui::AClass
类的一个实例。通过这个
ui
对象,你可以访问并操作在设计师中创建的窗体组件。
例如,你可以使用
ui
对象来设置窗体中的控件的属性,或在代码中对控件进行操作。例如,如果你在设计师中创建了一个名为
pushButton
的按钮控件,你可以使用
ui.pushButton
来访问和操作该按钮控件。
总的来说,
Ui::AClass
是一个自动生成的用户界面类,它用于描述与窗体
A
相关联的用户界面,并通过
ui
对象提供对窗体组件的访问和操作。这种分离窗体逻辑与用户界面描述的设计方式,使得代码更加模块化和易于维护。
A.cpp
// A.cpp#include"A.h"A::A(QWidget *parent):QMainWindow(parent){
ui.setupUi(this);
ui.textBrowser->insertPlainText("This is a text from A.cpp!\n");}A::~A(){}
这段代码定义了类
A
的构造函数和析构函数的实现,其中在构造函数中通过
ui.setupUi(this);
将用户界面与窗体关联。
A::A(QWidget *parent) : QMainWindow(parent)
:这是类
A
的构造函数的实现部分。在构造函数中,首先调用了父类
QMainWindow
的构造函数,使用
parent
参数来初始化基类。
接着,通过
ui.setupUi(this);
调用了
ui
对象的
setupUi
函数,将
ui
对象与当前的窗体对象
this
(即类
A
的实例)关联起来。这样,
ui
对象就可以用来访问与窗体
A
相关联的用户界面组件。
A::~A()
:这是类
A
的析构函数的实现部分。析构函数在对象被销毁时自动调用,用于释放对象的资源。在这里,析构函数不做任何额外的操作,因为没有需要手动释放的资源。
至于为什么是
A::A(QWidget *parent)
,而不是
A:A(QWidget *parent)
?
这是因为对于 C++ 中的构造函数和析构函数,正确的语法是使用两个冒号::
来指明函数所属的类,而不是一个冒号
:
。这是C++中的命名空间解析操作符(scope resolution operator)。所以,在构造函数的定义中,应该是
A::A()
而不是
A:A()
。同样,析构函数的定义应该是
A::~A()
而不是
A:~A()
。
在这里,A::
表示
A
类中的成员函数,
A(QWidget *parent)
表示构造函数的名称,
~A()
表示析构函数的名称。函数名前面的
A::
是用来限定这些函数是属于
A
类的。
如果在构造函数或析构函数的定义中使用了错误的语法(例如A:A()
或
A:~A()
),编译器会报错并指出无法找到匹配的函数声明。
修改后
接下来将创建一个
test.h
和一个
test.cpp
文件,并实现在
test.cpp
中调用 ui 中的控件
textBrowser
,并打印出来一段文字标记来自
test.cpp
。最终效果如下图所示:
A.h
// A.h#pragmaonce#include<QtWidgets/QMainWindow>#include"ui_A.h"#include"test.h"// new codeclassA:publicQMainWindow{
Q_OBJECT
public:A(QWidget *parent =nullptr);~A();private:
Ui::AClass *ui;// change code
c_test mc_test;// new code};
修改后的
A.h
相较于之前的,添加了
#include "test.h"
,这是一个预处理指令,用于包含名为
test.h
的头文件。这意味着您在
A.h
中引入了
test.h
文件中定义的内容,可能是另一个自定义类或者功能模块。我们这里属于引入了自定义类
test
。
Ui::AClass *ui;
:这是类
A
的一个私有成员变量的修改。原来的代码中使用的是
Ui::AClass ui;
,表示
ui
是一个
Ui::AClass
类型的对象。而在这个修改后的代码中,使用了
Ui::AClass *ui
;,表示
ui
是一个
Ui::AClass
类型的指针。这个修改是为了在类
A
中使用指针来管理
ui
对象的生命周期和资源释放,方便咱们在
test.h
中访问。
c_test mc_test;
:这是一个新的类成员变量,它是通过
test.h
头文件定义的
c_test
类的实例。现在在
A
类中拥有一个名为
mc_test
的
c_test
类对象。
mc_test
可以用来访问和操作
c_test
类中的成员。
这些变化是希望在
A
类中使用名为
c_test
的自定义类,并且想要通过指针动态地管理
ui
成员变量。
A.cpp
// A.cpp#include"A.h"A::A(QWidget *parent):QMainWindow(parent){
ui->setupUi(this);
ui->textBrowser->insertPlainText("This is a text from A.cpp!\n");
mc_test.p_ui = ui;// new code
mc_test.testFun();// new code}A::~A(){}
mc_test.p_ui = ui;
:这是新添加的代码行,它将
ui
指针赋值给名为
mc_test
的
c_test
类对象
p_ui
成员变量。根据代码可以看到,
mc_test
对象具有一个成员变量
p_ui
,用于存储
ui
指针的值。
mc_test.testFun();
:这也是新增的代码行,它调用
c_test
类对象
mc_test
的
testFun()
成员函数。根据代码的意思,
testFun()
函数是
c_test
类中的一个成员函数,根据函数定义(看
test.cpp
文件)也可以知道,它利用了存储在
p_ui
成员变量中的
ui
指针,以实现与 UI 相关的功能。
需要注意的是,因为对
A.h
进行了修改,将
ui
成员变量从对象变为了指针。因此,在
A.cpp
中使用
ui
时,需要使用
ui->
来访问其成员,而不再是
ui.
,例如
ui->setupUi(this)
和
ui->textBrowser->insertPlainText("This is a text from A.cpp!\n")
。
test.h
// test.h#ifndefTEST_H#defineTEST_H#include"ui_A.h"classc_test{public:
Ui::AClass* p_ui;voidtestFun();};#endif
#include "ui_A.h
:这一行包含名为
ui_A.h
的头文件,它是通过 Qt 的 UI 设计器从
A.ui
生成的头文件。这个头文件中包含了 UI 文件中定义的类和组件。
Ui::AClass* p_ui;
:这是
c_test
类的成员变量,它是一个指向
Ui::AClass
类型的指针。根据之前的代码,
Ui::AClass
是通过 UI 文件生成的用户界面类,而
p_ui
指针将用于存储
A
类中的
ui
指针,以便在
c_test
类中访问和操作
A
类的UI组件。
void testFun();
:这是
c_test
类的成员函数声明。根据之前在
A.cpp
中的调用
mc_test.testFun()
,这个函数被用于实现一些与 UI 相关的功能,使用了存储在
p_ui
成员变量中的
ui
指针。
现在,可以在
test.cpp
中实现
test.h
中声明的成员函数,以及根据需要与ui进行交互。
test.cpp
// test.cpp#include"test.h"void c_test::testFun(){
p_ui->textBrowser->insertPlainText("This is a text from test.cpp!\n");}
#include "test.h"
:这是包含
test.h
头文件,这样就可以访问
test
类的声明和成员函数定义。
void c_test::testFun()
:这是
c_test
类的成员函数
testFun()
的实现。根据代码的内容,这个函数将在
A
类的 UI 组件
textBrowser
中插入一行文本。这里的实现通过使用
p_ui
成员变量来访问 A 类中的
ui
指针,因为
p_ui
指向
Ui::AClass
类型,而
textBrowser
是
Ui::AClass
类中的一个成员。
总结一下,
test.cpp
中的代码通过使用存储在
p_ui
成员变量中的
ui
指针,成功在
A
类的
textBrowser
中插入了一行文本。这样,
c_test
类就可以与
A
类的 UI 组件进行交互。
Ref.
- Qt中,在另一cpp文件操作ui界面的相关控件
- [Qt] [UI] 多个类中操作同一个UI界面
版权归原作者 Zhao-Jichao 所有, 如有侵权,请联系我们删除。