知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。
还整了一个如何在其他文件中调用 ui 控件的文章,感兴趣可以看:【Visual Studio】Qt 在其他 cpp 文件中调用操作 ui 界面控件。
文章目录
- 创建一个原始工程名字为 A
- `A.ui`
- `A.h`
- `A.cpp`
- `main.cpp`
- 修改后
- `A.h`
- `A.cpp`
- `test.h`
- `test.cpp`
- `main.cpp`
- Ref.
- Ref.
主界面工程为 A
,添加的文件名字为 test
,目标是在 test
文件里操作 A
工程里的函数。
简洁版直接看这个截图就行,大意就是将老的实例化 ui
变成指针,将地址传递给 p_ui
,然后通过调用 p_ui
来间接调用 ui
。
名称解释:
c_test
表示新建的类p_ui
表示新建的类里的指针类型的成员变量testFun()
表示新建的类的函数mc_test
实例化的类,用来调用新建的c_test
的类
详细版可以看下边这些。
创建一个原始工程名字为 A
为了更好地演示,首先创建一个原始工程,名字为 A
,定义一个函数 inAFun()
,函数功能是打印一段文字。效果如下图所示:
工程的四个项目文件分别如下:
A.ui
A.h
// A.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_A.h"
class A : public QMainWindow
{
Q_OBJECT
public:
A(QWidget* parent = nullptr);
~A();
private slots:
void inAFun();
private:
Ui::AClass ui;
};
A.cpp
// A.cpp
#include "A.h"
A::A(QWidget* parent) : QMainWindow(parent)
{
ui.setupUi(this);
inAFun();
}
A::~A()
{}
void A::inAFun()
{
ui.textBrowser->insertPlainText("This is a text from A.cpp!\n");
}
main.cpp
// main.cpp
// main.cpp
#include "A.h"
#include <QtWidgets/QApplication>
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
A w;
w.show();
return a.exec();
}
修改后
接下来将创建一个 test.h
和一个 test.cpp
文件,并实现在 test.cpp
中调用 A.cpp
中的函数 inAFun()
,也会打印出来一段文字标记来自 inAFun()
。最终效果如下图所示:
A.h
// A.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_A.h"
class A : public QMainWindow
{
Q_OBJECT
public:
A(QWidget* parent = nullptr);
~A();
public slots: // 变更为 public 或者 public slots
void inAFun();
private:
Ui::AClass ui;
};
确保 inAFun()
函数在 A
类中是 public
或者是 public slots
,只有这样才能在其他类中使用。
A.cpp
// A.cpp
#include "A.h"
A::A(QWidget* parent) : QMainWindow(parent)
{
ui.setupUi(this);
inAFun();
}
A::~A()
{}
void A::inAFun()
{
ui.textBrowser->insertPlainText("This is a text from A.cpp!\n");
}
不用改动。
这里的详细解释可以参考:【Visual Studio】Qt 在其他 cpp 文件中调用操作 ui 界面控件。
test.h
// test.h
#pragma once
#include "A.h"
class c_test
{
public:
c_test(A* a_ptr); // 在构造函数中接收一个 A 类的指针
~c_test();
void callAFunction();
private:
A* a_object; // 储存一个 A 类的指针
};
在 test.h
中包含 A.h
。
test.cpp
#include "test.h"
c_test::c_test(A* a_ptr) : a_object(a_ptr) // 初始化 A 类的指针
{}
c_test::~c_test()
{}
void c_test::callAFunction()
{
a_object->inAFun(); // 通过 A 类的指针来调用 inAFun() 方法
}
重点看一下 c_test::c_test(A* a_ptr) : a_object(a_ptr)
:是使用初始化列表语法来初始化 c_test
类的 a_object
成员。这行代码的意思是,当 c_test
类的对象被构造时,它的 a_object
成员应该被初始化为传递给 c_test
类构造函数的参数 a_ptr
。这样,就能够在 c_test
类的其他方法中,通过 a_object
指针访问 A
类的对象了。
C++ 的初始化列表语法。初始化列表出现在构造函数后面,由冒号开始,并包含一个或多个用逗号分隔的成员初始化器。每个成员初始化器由一个数据成员(或基类)的名称和一对括号组成,括号内包含了用来初始化该数据成员的值或表达式。
这种初始化方式主要有两个优点:
更高效:对于某些类型的数据成员(如 const 或引用类型),你必须在构造函数体外进行初始化,因为这些类型的成员变量不能在构造函数体内被赋值。即使对于那些可以在构造函数体内赋值的数据成员,使用初始化列表通常也会更高效,因为它可以避免先调用默认构造函数再调用赋值操作符的额外开销。
更安全:如果一个类的数据成员是另一个类对象,而后者的构造函数需要一些参数,那么你就需要在初始化列表中传递这些参数,否则你无法在构造函数体内进行初始化,因为此时对象已经被默认构造函数构造好了。
main.cpp
// main.cpp
#include "A.h"
#include "test.h" // 包含 test.h 文件
#include <QtWidgets/QApplication>
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
A w;
w.show();
c_test mc_test(&w); // 传递 A 类对象的地址给 c_test 类的构造函数
mc_test.callAFunction(); // 调用 Test 类的 callAFunction() 方法,这会触发 A 类的 inAFun() 方法
return a.exec();
}
现在,当运行程序时,main.cpp
文件会创建一个 A
类的对象并展示它的窗口。
然后创建一个 c_test
类的对象,并将 A
类的对象的地址作为参数传递给 c_test
类的构造函数。这时 callAFunction()
方法就能够调用 A
类的 inAFun()
方法,而且你应该能够在 A
类的 QTextBrowser
中看到 inAFun()
插入的文本。
Ref.
- Qt中,在另一cpp文件操作ui界面的相关控件
- [Qt] [UI] 多个类中操作同一个UI界面
Backup
// main.cpp
#include "GUI_NatNet_VTK.h"
#include <QtWidgets/QApplication>
GUI_NatNet_VTK* w;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
w = new GUI_NatNet_VTK();
w->show();
return a.exec();
}
// GUI_NatNet_VTK.h
private slots:
void on_pushButtonStart_clicked();
void on_pushButtonPause_clicked();
void on_pushButtonStop_clicked();
void discoverNatNet();
void connectNatNet();
friend void displayMotion(GUI_NatNet_VTK &p_ui, double **dynamicArray);
\\ GUI_NatNet_VTK.cpp
void displayMotion(GUI_NatNet_VTK& p_ui, double **dynamicArray)
{
p_ui.ui.labelRBX->setText(QString::number(dynamicArray[0][0]));
p_ui.ui.labelRBY->setText(QString::number(dynamicArray[0][1]));
p_ui.ui.labelRBZ->setText(QString::number(dynamicArray[0][2]));
}
Ref.
- C++ 友元函数