Qt笔记

AbstractButton(抽象按钮)

clicked 点击了
pressed 按下
released 释放
toggled 切换的
triggered 触发的

QT | 设置应用程序名称和主窗口标题

w.setWindowTitle("qt程序");

QT主窗口关闭并且关闭其他窗口

在Qt中,如果你想要在关闭主窗口时同时关闭所有其他窗口,你可以通过连接主窗口的closeEvent()信号到其他窗口的关闭槽函数来实现。

mainwin.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

#include <QMainWindow>
#include <QCloseEvent>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow {
Q_OBJECT

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

protected:
void closeEvent(QCloseEvent *event) override { //override 虚函数
// 关闭所有其他窗口
// 你需要有一个指针或者引用列表来存储这些窗口
#if 0 //下面方法二选其一
foreach (QWidget *widget, otherWindows) {
widget->close();
}
#else
foreach(auto widget,otherWin)
{
widget->close();
}
#endif
event->accept(); // 接受关闭事件
}

private:
MainWindow_Debug * mainWindow;
QList<QWidget*> otherWindows; // 存储其他窗口的列表

private:
Ui::Widget *ui;
};
mainwin.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
MainWindow::MainWindow(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{
ui->setupUi(this);

​ this->mainWindow = new MainWindow_Debug(parent);

​ this->mainWindow->show();

​ otherWin.push_back(this->mainWindow);

}
MainWindow::~MainWindow()
{
delete ui;
}

阻塞父窗口

实现父窗口被阻塞、只能操作当前窗口的这类窗口被称为模态窗口(Modal Window),Qt 提供了多种实现模态窗口的方式,核心分为应用程序级模态窗口级(父级)模态,实现方式不同

1
2
3
4
5
6
7
8
9
10
```





# 解决QT中文显示乱码问题

## 方法一:简单粗暴

ui.label->setText(u8”显示汉字”);//使用方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

其他方法请参考:https://developer.aliyun.com/article/1256040



# `QT`创建的对象是否需要`delete`

Qt中,如果你使用了`new`关键字来创建对象,并且该对象的生命周期不是由Qt的对象树(object tree)管理的,那么你需要负责在适当的时候使用`delete`来释放这个对象。

Qt提供了一些规则来帮助判断是否需要手动删除对象:

1. 如果你使用`new`来创建对象,那么你需要使用`delete`来释放它。
2. 如果对象是通过Qt的动态信号和槽连接机制创建的(比如通过`connect`函数使用`new`创建的lambda表达式或者是QObject的子类),那么你需要负责删除这些对象。
3. 如果对象是通过Qt的对象树创建的(比如通过`QWidget`的子类创建的部件,并且设置了非null的父对象),那么当父对象被删除时,它的子对象也会被自动删除。
4. 如果你使用了Qt的内存管理助手宏 `Q_DECLARE_METATYPE` 并且将你的自定义类型注册到了Qt的类型系统中,那么你需要确保当不再需要这个对象时,使用`delete`来释放它,因为Qt的信号和槽机制会自动对其进行复制。

// 需要手动删除
MyObject *obj = new MyObject();
// … 使用obj
delete obj;

// 不需要手动删除,当父对象被删除时,子对象会自动被删除
QWidget *window = new QWidget();
QPushButton *button = new QPushButton(window);
// … 使用button
// 当不再需要window时,可以通过delete window;来自动删除button
delete window;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

实际编程中,确保在对象不再需要时正确地删除它们非常重要,否则会导致内存泄漏。

如果你使用智能指针(如`QSharedPointer`或`std::unique_ptr`),它们会自动管理对象的生命周期,从而减少内存泄漏的风险。





# 项目中获取当前路径

代码里路径直接用`$$PWD`取当前路径,再接库目录的路径



# QT信号与槽多种表达方式

## connect

### 使用QObject指针和成员函数指针

QObject::connect(sender, SIGNAL(signalName()), receiver, SLOT(slotName()));

1
2
3
4
5

### 使用函数指针(C++11及以后)

从Qt 5开始,推荐使用新的连接语法,特别是在C++11及以后的版本中,你可以直接使用函数指针:

connect(sender, &SenderClass::signalName, receiver, &ReceiverClass::slotName);

1
2
3
4
5

### 使用Lambda表达式(C++11及以后)

Lambda表达式提供了一种灵活的方式来定义槽,而不需要定义独立的槽函数:

connect(sender, &SenderClass::signalName, ={
// Lambda表达式中的代码,相当于槽的函数体
});

1
2
3
4
5
6

#### 注意事项

- **信号和槽的名称**:在使用旧式字符串语法时(`SIGNAL`和`SLOT`宏),信号和槽的名称必须是有效的。在C++11及以后,你可以直接使用成员函数的指针。
- **线程安全**:确保信号和槽在相同的线程中执行,或者使用`Qt::QueuedConnection`、`Qt::DirectConnection`、`Qt::AutoConnection`等连接类型来控制信号和槽的执行方式。例如,跨线程通信时使用`Qt::QueuedConnection`:

connect(sender, &SenderClass::signalName, receiver, &ReceiverClass::slotName, Qt::QueuedConnection);

1
2
3

- **断开连接**:使用disconnect函数可以断开之前建立的连接,以避免内存泄漏或不必要的回调。例如:

disconnect(sender, &SenderClass::signalName, receiver, &ReceiverClass::slotName);

1
2
3
4
5
6
7





# 添加不在项目路径中的文件

.pro 文件配置

INCLUDEPATH += $$PWD/3rdparty/libusb/include # 头文件路径
LIBS += -L$$PWD/3rdparty/libusb/lib # 库文件路径

根据平台链接具体库

win32 {
LIBS += -llibusb-1.0 # Windows 下链接 libusb-1.0.lib
}
unix {
LIBS += -lusb-1.0 # Linux/macOS 下链接 libusb-1.0.so/dylib
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51





# QT创建线程

## 方案一:

### 一、继承 `QThread` 并重写 `run()`(传统方法)

这是最经典的线程创建方式,通过继承 `QThread` 类,重写其 `run()` 函数(线程入口点)实现线程逻辑。

### 实现步骤:

1. 自定义类继承 `QThread`;
2. 重写 `run()` 函数,线程启动后会执行 `run()` 中的代码;
3. 调用 `start()` 启动线程(而非直接调用 `run()`)。

### 示例代码:

```c++
#include <QThread>
#include <QDebug>

class MyThread : public QThread {
Q_OBJECT
protected:
void run() override {
// 线程执行的逻辑(耗时操作等)
for (int i = 0; i < 5; ++i) {
qDebug() << "线程运行中:" << i << " 线程ID:" << currentThreadId();
msleep(1000); // 休眠1秒(QThread的成员函数)
}
qDebug() << "线程结束";
}
};

// 使用方式
#include <QApplication>

int main(int argc, char *argv[]) {
QApplication app(argc, argv);

MyThread thread;
thread.start(); // 启动线程(会自动调用run())
// 主线程继续执行其他逻辑
qDebug() << "主线程ID:" << QThread::currentThreadId();

return app.exec();
}