moc

uic

内嵌、非内嵌

模态、非模态

三个窗口的区别

setFixedSize();
move();
setText();
setWindowTitle();
QIcon();

QPushButton
QLabel
QPixmap 图片容器
load() // 装载图片
setPixmap();// 标签设置图片
// 图片自适应标签大小
setScaledContents();

listWidget
addItem()   // 添加成员
QListWidgetItem(); // 创建 item 对象。QListWidgetItem(QIcon("xxxx.ico"),"xxx");// 带图标
sortItems()

comboBox
addItem()
addItem(QIcon(""),"");

slider
setValue(); // 滑动条设默认值

LineEdit
setText() // 设置文本
setEchoMode() // 设置显示格式
setMaxLength();
clear(); // 清空
text(); // 获取文本信息

processBar
setValue();

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

Qt 资源文件

信号与槽

标准信号和标准槽函数

非标准信号和非标准槽

signal

clicked();
clicked(bool);
pressed();
released();
toggled(bool);// 双击


slots

close();
1
2
3
4
5
6
7
8
9
10
11
12

信号

singals

返回值 void

可以有参数,可以重载

只需要定义,不用实现

主动发送信号用 emit。

槽函数

slots

返回值是 void

可以有参数,可以重载

connect(发送者, 信号, 接收者, 槽函数);

信号和槽函数连接的条件:

  1. 信号函数的参数必须大于等于槽函数的参数个数,信号中多余的参数会被忽略。
  2. 信号和槽函数对应位置的参数必须保持一致。

Qt5 使用 connect 将信号与槽函数连接,不需要再使用 SIGNAL() 和 SLOT() 宏

槽函数也不用写到 slots 中。

# 对话框 Dialog

文件对话框,QFileDialog

getOpenFileDialog();
QDir::currentPath();    // 当前路径

QVBoxLayout 垂直布局

setMargin //设置间隔
addWidget // 添加部件
1
2
3
4
5
6
7

消息对话框 QMessageBox

QMessageBox::about();
QMessageBox::information(); // 提示
QMessageBox::aboutQt();
QMessageBox::critical();    // 严重错误提示
QMessageBox::question();    // ?
QMessageBox::warning();    // 警告
 int ret = QMessageBox::warning(this, tr("My Application"),
                                 tr("The document has been modified.\n"
                                    "Do you want to save your changes?"),
                                 QMessageBox::Save | QMessageBox::Discard
                                 | QMessageBox::Cancel,
                                 QMessageBox::Save);
1
2
3
4
5
6
7
8
9
10
11
12

输入对话框 QInputDialog

QInputDialog::getText();
1

颜色对话框

QColor color = QColorDialog::getColor();
Qr::red;
QPalette pe;
pe.setColor(QPalette::Window, color);
this->setPalette(pe); // 设置窗口的颜色

1
2
3
4
5
6

字体对话框 QFontDialog

QFont font = QFontDialog::getFont();
1

自定义对话框

继承 QDialog
1

# 主窗口

标题栏、状态栏、工具栏(上下左右)、浮动停靠窗口、中央窗体

QAction

// * 标题栏
this->resize(1000,618);
this->setWindowTitle("主窗口");
this->setWindowIcon(QIcon(":/ico/4.png"));
// 设置中心窗口为文本编辑器
QTextEdit *text = new QTextEdit(this);
this->setCentralWidget(text);

// * 添加动作
#include <QAction>
// &打开文件,悬停效果
QAction *openfile_action = new QAction(QIcon(),"&打开文件"this);

// * 添加菜单
#include <QMenuBar>
// 添加热键
QMenu *file_menu = menuBar()->addMenu("文件(&F)");
QMenu *editMenu = menuBar()->addMenu("编辑(&E)");
// 菜单栏里添加菜单项
fileMenu->addAction(openFileAction);
fileMenu->addSeparator(); // 添加分隔符
editMenu->addAction(editMenuAction);
// 工具栏
#include <QToolBar>
// 添加工具栏
QToolBar *tb = QMainWindow::addToolBar("tool");
// 工具栏只能在上面
tb->setAllowedAreas(Qt::TopToolBarArea);
tb->setMovable(false); // 设置不可移动
tb->addAction(openFileAction);
tb->addSeparator();// 添加分隔符
tb->addAction(editFileAction);

// 添加状态栏
#include <QStatusBar>
#include <QLabel>
// 会在第一次调用创建状态栏。
QStatusBar *sb = QMainWindow::statusBar();
// 添加状态
QLabel *label = new QLabel("ready", this);
label->setMaxinumWidth(this->width());
sb->addWidget(label);

// 连接动作和槽
connect(openFileAction, &QAction::triggered,this, &openfile);
// 添加快捷键
openFileAction->setShortcut(QKeySequence("Ctrl+o"));
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

# Qt 操作文件

QByteArray适合的两个主要情况是当您需要存储原始二进制数据, 并且当内存保护至关重要时(例如,使用嵌入式Linux的Qt)

#include <QFile>

QFile file(path);
file.open(QIODevice::ReadOnly);

QByteArray arr = file.readAll();
ui->textEdit->setText(arr);

file.close();

// 写文件
file.open(QIODevice::Append);
file.write("内容");

// 读取一行数据

file.readline();

#include <QFileInfo>// 文件信息

QFileInfo info(path);
info.suffix(); // 查看文件的后缀名
info.size(); // 文件的大小
info.path(); // 查看文件的路径
info.created().toStrong("dd.MM.yyyy"); // 查看文件的创建时间
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

# Qt 的模块

QtCore Qt Network Qt QML Qt SQL

# Qt5 中信号与槽的新写法

connect(sender, &Sender::valueChanged,
        receiver, &Receiver::updateValue);
1
2

新语法的好处:

  1. 编译器检查。

  2. 参数的自动类型转换。

class Test : public QObject
{
    Q_OBJECT
public:
    Test() {
        connect(this, &Test::someSignal, this, &Test::someSlot);
    }
signals:
    void someSignal(const QString &);
public:
    void someSlot(const QVariant &);
};
1
2
3
4
5
6
7
8
9
10
11
12

在新语法中,QString 将被自动转换成 QVariant。

  1. 连接到任意函数

signal 被连接到了一个 public 函数,但这个函数并不是 slot。 Qt 的新语法通过函数指针直接调用函数,而不需要 moc 的特殊处理(但是 signal 依然需要)。

connect(sender, &QObject::destroyed, this, [=](){ this->m_objects.remove(sender); });
1

# 事件分发器

事件派发 -> 事件过滤 -> 事件分发 -> 事件处理。

void keyPreddEvent(QKeyEvent *event) override; // 按键按下事件
QPixmap pix;
pix.load("");
QPoint point = ui->label->pos();
point.setY(point.y() - 10);
point.setX();
label->move(point);
void keyReleaseEvent(QKeyEvent *event) override; // 按键松开
void mousePressEvent(QMouseEvent *event) override;// 鼠标按下
event->x();
event->y();
void mouseReleaseEvent(QMouseEvent *event) override; // 鼠标松开
void mouseMoveEvent(QMouseEvent *event) override; // 鼠标移动
void enterEvent(QEvent *event) override; // 鼠标进入窗口事件
void moveEvent(QMoveEvent *event) override; // 窗口移动事件
#include <QTimerEvent>
// 定时器事件
void timerEvent(QTimerEvent *event) override; // 定时器
// 定时器唯一标识
int id = startTimer(200);// 0.2s 触发一次定时器事件6
// 开启定时器: startTimer ,单位 ms
startTimer();
// 关闭定时器: killTimer
killTimer(id)
event->timerId();// 获取 定时器 id
// 拦截事件分发器,需要重写 event 函数
// 不建议重写事件分发器
// 事件分发器函数
bool QWidget::event(QEvent *event) override;
QEvent::type(); // 判断是什么世界
return QWidget::event(event); // 表示其他事件正常处理
// 事件过滤器,过滤事件让其不经过事件分发器。
// 事件过滤器不建议重写
// watched: 表示装载过滤器的空间
bool QWidget::eventFilter(QObject * watched, QEvent *event) override;
// 装载事件过滤器
widget::installEventFilter(this);
// 重写过滤器
if (watched == ui->xx) {
    // 执行过滤操作
    if (event->type() == Qt::keyPress) {
        QKeyEvent *e = dynamic_cast<QKeyEvent *>(event);
        如果按下的是 空格键
        ……

    }
}
// 指针转换
// * 绘图事件
// 2D 绘图
#include <QPaintEvent>
#include <QPainter>
void paintEvent(QPaintevent *event) override;
QPainter painter(this); // this 表示绘画设备
painter.drawLine(QPoint(0,0), QPoint(500,500)); //画线
painter.drawEllipse(QPoint(300,300),100, 100); //画圆
painter.drawRect(100,200,200,150); // 画矩形
painter.drawText(QRect(0,500,100,50),QStrint("画家正在画字")); // 画字
#include <QPen> // 画笔
#include <QBrush> // 画刷

// 创建画笔
QPen pen;
pen.setStyle(Qt::DotLine);
pen.setColor(Qt::red);
pen.setWidth(2);
painter.setPen(pen);
QBrush brush;// 封闭图形上色
brush.setColor(Qt::blue);
brush.setStyle(Qt::SolidPattern);
painter.setBrush(brush);

// 绘画事件和鼠标事件结合,用鼠标在界面上作画

update(); // 强制更新

// 抗锯齿,速率慢
painter.setRenderHint(QPainter:Antialiasing);
// 移动画家的位置
painter.translate();
painter.save(); // 保存画家的目前状况。
// 还原画家状态。
painter.restore();

// 画图片,设置背景图片
painter.drawPixmap(this->rect(),QPixmap(""),QRect());

// 数据库
#include <QSqlDatabase>
#include <QSqlQueryModel>

QSqlDatabase db;
QSqlQueryModel model;

// * 构造函数初始化
// **创建数据库
// 增加数据库驱动
db = QSqlDatabase::addDatabase("QSQLITE"):
// 设置数据库名称
db.setDatabaseName("student.db");
// 打开数据库
db.open();
// 创建表
QSqlQuery query;
query.exec("create table student(xxxx) ");
"create table student (id int primary key not null,
 name text not null,
 score real note null"
// 查询表
QSqlQuery query;
str = query.exec("xxx");
"select * from student"
model.setQuery(str);
tableView->setModel(&model);

"%1,%2,%3".arg(xx).arg(xx).arg(xx);

combox->currentIndex();

//   ---------------  线程---------

// Qt 4 方法
QThread 类。
继承 QThread 类

void run() override; // 线程处理函数,不能主动调用。
通过 start() 间接调用。
通过发送信号连接响应的槽函数
QThread::currentThreadId(); // 获取进程号
QThread::sleep(); // 休眠

MyThread *thread = new MyThread(this);

// Qt 5 方法

类继承 QObject 类

class MyThread: public QObject {
    // 自定义线程处理函数
    void work();
}

void MyThread::work() {
    while (1) {
        emit mysignals();
    }
}

// 创建线程对象
MyThread *thread = new MyThread;
// 创建 QThread 子线程对象
QThread *qthread = new QThread;
// 将自定义线程类放入到子线程对象中
thread->moveToThread(qthread);
qthread.start();    // 开启线程

connect(thread, &mysignals, this, [](){

});

注意:

1. 启动子线程,只是启动了线程,并没有启动线程处理函数。
2. 线程函数的启动必须通过信号和槽。


线程退出:

slots:
quit(); // 退出,等待事情做完再退出。
terminate(); // 强制退出


// -------------- 网络编程 -------------------
#include <QTcpServer>
#include <QTcpSocket>

服务器:
QTcpServer  *server;// 监听套接字
server = new QTcipServer(this);
QSocketServer *t;
// 开启服务器
connect(xxx,&xxx,this,[](){
    // 监听套接字
    server->listen(QHostAddress::Any, "port号".toShort());
});

// 处理客户端的连接
connect(server, &QTcpServer::newConnection,this,[=](){
    // 取出通信套接字
    t = server->nextPendingConnection();
    // 读取数据
    connect(t, &TcpSocket::readyRead, this, [](){
        QString recvMsg = t->readAll(); // 读取数据
        recvMsg.toUgf8();
    });
    // 处理断开连接
    connect(t, &TcpSocket::disconnected, this,[=](){
        // 删除通信套接字
        t->deleteLater();
    });
});

// 发送数据
connect(xxx,&xxx,this,[=](){
    QString sendMsg = textEdit->toPlainText(); // 获取消息发送的内容
    t->write(sendMsg.toUtf8());
});

客户端:
QTcpSocket *client; // 通信套接字
connectToHost();    // 触发成功,服务器会触发 newConnection() 信号。

#include <QTcpSocket>

QTcpSocket *client; // 通信套接字

client = new QTcpSocket(this);
// 主动连接
connect(xxx,&xxx,this,[this](){
    this->client->connectToHost(ip, port.toShort());
});

// 处理连接信号
connect(client, &QTcpServer::connected, this, [](){});

// 读取数据
connect(client,&QTcpSocket::readyRead, this, [=](){
    QString recvMsg = client->readAll();
});

// 发送数据
connect(xxx,&xxx,this,[=](){
    QString sendMsg = xxx;
    client->write(sendMsg.toUtf8());
});

// 处理和服务器之间断开连接

connect(xxx,xxx,this,[=](){
    client->close();
})



// ---------------------------
// 单例模式
// 线程池

// 设置最大线程数

继承 QRunnable
重写 void run();
QThreadPool::globalInstance()->setMaxThreadCount();
QThreadPool::globalInstance()->start(work);

// json
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonValue>

QJsonObject obj;
obj.insert("","");
obj2.insert("",obj);
QJsonDocument doc(obj);
QBtyeArray json=json.toJson();
QFile file("xxx");
file.open("");
file.write(json);
file.close();

// 解析
QBtyeArray json = file.readAll();
auto doc = QJsonDocument::fromjson(json);
if (doc.isObject()) {

}

//---------------------------------------
// 串口编程
// 提供访问串口的功能
#include <QSerialPort>
// 提供系统中存在的串口信息
#include <QSerialPortInfo>
QserialPort serial;
serial.setPortName("");
// 波特率
// 数据位
// 奇偶校验
// 停止位
// 流控制
// 打开串口
// 读取数据

// --------------------------
Qt 打包

release 正式版本发布

打开 Qt 控制台

windeployqt xxx.exe

程序打包:Inno SetUp

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306

# Qt tools

moc:meta-object-complier,元对象编译器,mod 解析 Q_OBJECT 类的定义并且通过 C++ 函数提供可供使用的信息。

uic:user interface complier,用户界面编译器,用于将 xxx.ui 文件转换成 C++ 并且存储在 ui_xxx.h 文件中,其中会包含Ui::Xxx 的定义,生成的类没有任何基类,没有 setupUi() 用于初始化窗体。

# Qt 对象树

当一个QObject对象在堆上创建的时候,Qt 会同时为其创建一个对象树。

Qt 所有的窗口类以及部分非窗口类都继承自QObject,这些对象通过基类 QObject 组织成树状结构,这就是对象树。

对象树的好处就是:父对象被析构的时候,子对象也会被析构,qt对象树系统采用先序遍历的方式析构对象。这个机制非常适合于管理GUI对象,当顶层窗口销毁的时候,自动销毁子窗口。

在创建QObject对象时,可以提供一个其父对象(指定父亲),我们创建的这个QObject对象会自动添加到其父对象的children()列表。

因此可以在代码中肆意创建对象,只要指定父对象,父对象包含管理释放(析构),那么子对象在父对象析构的时候会自动析构。

最好从开始就养成良好习惯,在 Qt 中,尽量在构造的时候就指定 parent 对象,并且大胆在堆上创建,而且 UI 部件尽量不要使用智能指针管理。

还有注意一点,对象树对应的是父窗口部件和子窗口部件。向布局管理器添加部件是没有把添加的部件加入到孩子列表,将布局管理器安装到部件上后,添加到布局管理器里的部件会自动「重定义父对象」,当创建一个 需要放入某个布局的窗口部件,就不需要显式指定父对象。

# Qt 继承树

QObject -> QCoreApplication
        -> QWidget
        -> QLayout

QCoreApplication -> -> QGuiApplication -> QApplication

QLayout -> QBoxLayout

QBoxLayout -> QHBoxLayout

QWidget -> QAbstractButton
        -> QAbstractSpinBox
        -> QAbstractSlider
        -> QFrame
        -> QDialog
        -> QMainWindow
        -> QDialogButtonBox
        -> QTableView

QTableView -> QTableWidget
           -> QTableWidgetItem

QAbstractButton -> QPushButton

QAbstractSpinBox -> QSpinBox

QAbstractSlider -> QSlider

QFrame -> QLabel
       -> QToolBox
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

为了使 Qt 的item (项)类开销降到最低,item 类都不继承 QObject 类,不能实现信号和槽。

# QObject

Qt 中所有类都继承自 QObject。

核心功能:

  1. 信号与槽
  2. 事件处理,任何一个想要接受并处理事件的对象均须继承自QObject,可以选择重载QObject::event()函数或事件的处理权转给父类。
  3. 内存管理
// 连接信号和槽
// Qt5 写法
QObject::connect(sender,&signal,receiver, &slot);
// Qt4 写法
// 这种写法需要将槽函数在 slots: 中声明
QObject::connect(sender,SIGNAL(signal(参数列表)),receiver, SLOT(slot(参数列表));
// 翻译成其他语言的标记。
QObject::tr();
// 打印对象树信息
dumpObjectTree();
// 打印子对象
children();
// 调用这个函数,并不会直接进行delete,而是向事件循环发送了一个delete事件,也就说当控件返回到事件循环时,这个对象才会被删除。
deleteLater();



// Qt 强烈建议在QObject的所有子类中使用 Q_OBJECT 宏,无论它们是否实际使用信号、插槽和属性,
// 因为如果不这样做,可能会导致某些函数显示出奇怪的行为。

// 继承 QObject
class A : public QObject{
    Q_OBJECT
    A(QObject *parent = nullptr);
}
A(QObject *parent):QObject(parent){}
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

# QApplication

#include <QApplication>
// 构造函数,Qt 支持自己的一些命令行参数
QApplication app(argc, argv);
// 将程序控制权传递给 Qt
app.exec();
1
2
3
4
5

signals:

slots:

quit();
1

# QLabel

标签组件,支持展示文本、图片、HTML。

#include <QLablel>
// 构造函数
QLabel *label  = new QLabel("Hello, Qt");
// 设置伙伴关系
label->setBuddy(xxx);
// 设置标签内容的对齐方式
label->setAligment(Qt::AlignHCenter);
// 设置标签自适应,为设置QLabel自动缩放,既:显示图像大小自动调整为Qlabel大小。
label->setScaledContents(true);
1
2
3
4
5
6
7
8
9

# QPushButton

按钮组件

#include <QPushButton>
// 构造函数
QPushButton *button = new QPushButton("text");
button->setDefault(bool); // 设置此按钮为 Enter 默认按钮
button->setEnabled(bool); // 控制按钮是否可交互
1
2
3
4
5

signals:

clicked();
clicked(bool);
1
2

# QSpinBox

微调框

#include <QSpinBox>
QSpinBox *spinBox = new QSpinBox;
spinBox->setRange(num,num); // 设置微调框范围
spinBox->setValue(num);
1
2
3
4

signals:

valueChanged(int);
1

slots:

setValue(int);
1

# QSlider

滑块

#include <QSlider>
// 构造水平滑块
QSlider *slider = new QSlider(Qt::Horizontal);
slider->setRange(num,num); // 设置范围
1
2
3
4

signals:

valueChanged(int);
1

slots:

setValue(int);
1

# QWidget

QWidget 的构造函数以及它的所有子类都会带有一个 QWidget *parent 参数,用来指定父窗口部件。 parent 为 nullptr 则意味着部件没有父对象。

// 构造函数
QWidget *widget = new QWidget;
// 设置窗口标题
widget->setWindowTitle("title");
// 为窗口安装布局
widget->setLayout(xxx);
// 显示非模式窗口
// 窗口不会阻塞,可以随意操作;
widget->show();
// 显示半模式窗口
// 窗口会原地伪阻塞,虽然也是只能操作该窗口,
// 其余窗口不能再操作,但是代码会继续往下运行,所以说是伪阻塞;
widget->setModal(true);
widget->show();
// 模态
// Qt::NonModal 不阻塞
// Qt::WindowModal 阻塞父窗口,所有祖先窗口及其子窗口
// Qt::ApplicationModal 阻塞整个应用程序
setWindowModality(Qt::ApplicationModal);        //设置阻塞类型
setAttribute(Qt::WA_ShowModal, true);           //属性设置 true:模态 false:非模态
// 模式窗口,窗口会原地阻塞,只能操作该窗口,其余窗口不能再操作;
// 只有关闭该窗口后,代码处才会获得返回值,阻塞停止,就可以操作其它界面了
widget->exec();
// 设置固定高度
widget->setFixedHeight(xxx);
// 返回一个窗口部件的理想尺寸大小
widget->sizeHint();
// 安装布局
widget->setLayout(xx);
// 设置Tab 顺序
widget->setTabOrder();
// 隐藏窗口
widget->hide();
// 设置最小窗口
widget->setMinimumSize();
// 关闭窗口时自动调用
closeEvent(QCloseEvent *event) override;
// 设置窗口图标
widget->setWindowIcon();
// 给界面设置上下文菜单
// 这个属性的默认值是  Qt::DefaultContextMenu
// 这意味着会调用  contextMenuEvent(),可以重写此函数,
// 在函数内创建一个 QMenu,在其中添加动作,然后对窗口部件调用 exec()

// 属性为:Qt::ActionsContextMenu 时,
// 直接给 widget 添加 动作即可。
setContextMenuPolicy(Qt::ContextMenuPolicy policy);
// 设置是否显示窗口内有修改但未保存的内容
setWindowModified(bool);
// 关闭窗口时自动调用
void closeEvent(QCloseEvent *event);
// 设置样式表
QString pushButton_SS = "QPushButton{border-radius: 10px; /*圆角半径*/color:green;/*字体颜色*/}";
widget->setStyleSheet(pushButton_SS);
// 设置对齐方式
widget->setAligment();
// 指定控件坐标和控件的宽高。
// 表示该界面显示在屏幕的100和100的位置
w.setGeometry(100,100,200,120);
// 其中move的原点是父窗口的左上角,  如果没有父窗口,则桌面即为父窗口
// x往右递增,y往下递增
void move(int x, int y);
void move(const QPoint &);
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
52
53
54
55
56
57
58
59
60
61
62
63

signals:

accepted();
rejected();
1
2

slots:

close(); // 把窗口部件从用户的视野中隐藏起来,无须删除
1

# QHBoxLayout

水平布局管理器,水平方向上排列窗口部件,从左到右。

当创建一个需要放入某个布局的窗口部件时,不用显式指定父对象,他们会成为 安装了布局的窗口部件的子部件。

#include <QHBoxLayout>
QHBoxLayout *layout = new QHBoxLayout;
// 布局里添加组件
layout->addWidget(xxx);
// 布局里添加
layout->addLayout(xxx);
// 添加伸展器
layout->addStretch();
// 固定窗口的大小,且根据内部空间所占用的位置自动调节大小
setSizeConstraint(QLayout::SetFixedSize);
// 设置控件对齐方式
//Qt::AlignLeft    //水平方向靠左。
//Qt::AlignRight    //水平方向靠右。
//Qt::AlignHCenter    //水平方向居中。
//Qt::AlignTop        //垂直方向靠上。
layout->setAlignment(Qt::AlignLeft);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# QHBoxLayout

垂直布局管理器,垂直方向上排列窗口部件,从上到下。

# QGridLayout

网格布局管理器,把各个窗口排列到一个网格中。

//获取网格控件中的行数。
int QGridLayout::rowCount() const
// 获取网格控件中的列数。
int QGridLayout::columnCount() const
// 	将 widget 控件添加到网格中的 (row,column) 位置处,并且可以自定义该控件的对齐方式。
void QGridLayout::addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment = Qt::Alignment())
// 	将 widget 控件从 (fromRow, fromColumn) 位置开始,跨 rowSpan 行和 ColumnSpan 列添加到网格中,并且可以自定义该控件的对齐方式。
void QGridLayout::addWidget(QWidget *widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment = Qt::Alignment())
// 	向网格中的 (row, column) 位置处添加 layout 布局管理器。
void QGridLayout::addLayout(QLayout *layout, int row, int column, Qt::Alignment alignment = Qt::Alignment())
// 	将 layout 布局管理器从  (row, column) 位置开始,跨 rowSpan 行和 ColumnSpan 列添加到网格中,并且可以自定义该布局控件的对齐方式。
void QGridLayout::addLayout(QLayout *layout, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment = Qt::Alignment())
//给指定的 column 列设置伸缩系数。
void QGridLayout::setColumnStretch(int column, int stretch)
// 	给指定的 row 行设置伸缩系数。
void QGridLayout::setRowStretch(int row, int stretch)
//  	设置 column 列的最小宽度。
void QGridLayout::setColumnMinimumWidth(int column, int minSize)
// 	设置 row 行的最小宽度。
void QGridLayout::setRowMinimumHeight(int row, int minSize)

 QGridLayout *layout = new QGridLayout;
    //向 layout 中添加控件,并指定各个控件的位置
    layout->addWidget(but1, 0, 0);
    layout->addWidget(but2, 0, 2);
    layout->addWidget(lab3, 1, 0, 3, 3);
    layout->addWidget(but3, 4, 0);
    layout->addWidget(but4, 4, 2);
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

# QPixmap

图片

#include <QPixmap>
QPixmap pixmap;
// 加载图片
pixmap.load("path");
// qimage 转 pixmap
QPixmap a = QPixmap::Fromimage(qimage);
1
2
3
4
5
6

# QCheckBox

多选框

QCheckBox *checkBox = new QCheckBox("&xxx");
// 读取是否被选中
checkBox->isChecked();
1
2
3

signals:

accepted();
rejected();
1
2

slots:

# QLineEdit

行编辑器

QLineEdit *lineEdit = new QLineEdit;
// 输入框添加校验器
lineEdit->setValidator(校验器);
// 使用校验器判断行编辑器中内容的有效性,返回值 bool
lineEdit->hasAcceptableInput();
// 获取输入框的内容
lineEdit->text();
1
2
3
4
5
6
7

signals:

textChanged(const QString&);
1

slots:

# QDialog

对话框

signals:

slots:

accept(); // 将对话框的结果变量设置为 `QDialog::Accepted`
reject(); // 将对话框的结果变量设置为 `QDialog::Rejected`
1
2

# QRegularExpression

The QRegularExpression class provides pattern matching using regular expressions.

正则表达式。

QRegularExpression regExp("[A-Za-z][1-9][0-9]{0,2}");



// 简单匹配
// 匹配两个数字后跟一个空格和一个单词
// 如果匹配成功,(隐式)捕获组编号 0 可用于检索与整个模式字符串匹配的子字符串:
QRegularExpression re("\\d\\d \\w+");
QRegularExpressionMatch match = re.match("abc123 def");
if (match.hasMatch())
{
     QString matched = match.captured(0); // matched == "23 def"
     // ...
}

// 通过将偏移量作为 match() 函数的参数传递,也可以在字符串内的任意偏移量处开始匹配。 在以下示例中,“12 abc”不匹配,因为匹配从偏移量 1 开始:
QRegularExpression re("\\d\\d \\w+");
QRegularExpressionMatch match = re.match("12 abc 45 def", 1);
if (match.hasMatch())
{
    QString matched = match.captured(0); // matched == "45 def"
    // ...
}

// QRegularExpressionMatch 对象还包含有关由模式字符串中的捕获组捕获的子字符串的信息。 capture() 函数将返回第 n 个捕获组捕获的字符串:
QRegularExpression re("^(\\d\\d)/(\\d\\d)/(\\d\\d\\d\\d)$");
QRegularExpressionMatch match = re.match("08/12/1985");
if (match.hasMatch())
{
    QString day = match.captured(1); // day == "08"
    QString month = match.captured(2); // month == "12"
    QString year = match.captured(3); // year == "1985"
    // ...
}
// 模式字符串中的捕获组从 1 开始编号,隐式捕获组 0 用于捕获与整个模式匹配的子字符串。
// 通过使用 captureStart() 和 captureEnd() 函数,还可以检索每个捕获的子字符串的开始和结束偏移量:
QRegularExpression re("abc(\\d+)def");
QRegularExpressionMatch match = re.match("XYZabc123defXYZ");
if (match.hasMatch())
{
    int startOffset = match.capturedStart(1); // startOffset == 6
    int endOffset = match.capturedEnd(1); // endOffset == 9
    // ...
}

// 所有这些函数都有一个以 QString 作为参数的重载,以便提取命名的捕获子字符串。 例如:
QRegularExpression re("^(?<date>\\d\\d)/(?<month>\\d\\d)/(?<year>\\d\\d\\d\\d)$");
QRegularExpressionMatch match = re.match("08/12/1985");
if (match.hasMatch())
{
    QString date = match.captured("date"); // date == "08"
    QString month = match.captured("month"); // month == "12"
    QString year = match.captured("year"); // year == 1985
}

// 全部匹配
// globalMatch() 返回一个 QRegularExpressionMatchIterator,它是一个类似于 Java 的前向迭代器,可用于迭代结果。例如:
QRegularExpression re("(\\w+)");
QRegularExpressionMatchIterator i = re.globalMatch("the quick fox");

QStringList words;
while (i.hasNext())
{
    QRegularExpressionMatch match = i.next();
    QString word = match.captured(1);
    words << word;
}
// words 包含 "the", "quick", "fox"

// 或者:
QRegularExpression re(R"(\\w+)");
QString subject("the quick fox");
for (const QRegularExpressionMatch &match : re.globalMatch(subject))
{
    // ...
}

// Returns the expression wrapped between the \A and \z anchors to be used for exact matching.
// 返回包装在 \A 和 \z 锚点之间的表达式,以用于精确匹配
[static] QString QRegularExpression::anchoredPattern(QStringView expression);

QString QRegularExpression::anchoredPattern(QStringView expression) {
    return QString()
            + QLatin1String("\\A(?:")
            + expression
            + QLation1String("\\z");
}
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

# QRegularExpressionMatch

The QRegularExpressionMatch class provides the results of a matching a QRegularExpression against a string.

// Returns true if the regular expression matched against the subject string, or false otherwise.
// 如果正则表达式与主题字符串匹配,则返回true,否则返回false。
bool hasMatch();
1
2
3

# QLatiin1String

QLatin1String类对US-ASCII/Latin-1编码的字符串进行了简单封装,可理解为关于const char*的一个浅封装。

# QRegularExpressionValidator

正则表达式校验器,限制输入范围。

QRegularExpressionValidator(regExp, this); // 绑定父对象
1

# QDialogButtonBox

按钮框

QDialogButtonBox *buttonBox = new QDialogButtonBox;
buonBox->button(QDialogButtonBox::OK);
1
2

signals:

accepted();
accepted();
1
2

slots:


1

# QComboBox

下拉列表

// 清空下拉项
QComboBox::clear();
QComboBox::addItem("");
1
2
3

# QToolBox

# QRadioButton

单选按钮

# QToolButton

工具按钮

# QTabWidget

# QTextBrowser

文本展示框。

# QInputDialog

输入对话框

# QProgreddDialog

进度对话框

# QMessageBox

消息对话框

# QErrorMessage

错误消息

# QColorDialog

颜色对话框

# QFontDialog

字体对话框

# QFileDialog

文件对话框

# QtWizard

向导

# QMainWindow

主窗口

QMainWindow *mainWindow = new QMainWindow();
// 设置主窗口的中央部件
mainWindow->setCentralWidget(xxx);
// 返回一个主窗口的菜单栏,第一次调用创建一个菜单栏
mainWindow->menuBar();
// 添加工具栏
mainWindow->addToolBar();
1
2
3
4
5
6
7

# QAction

一个动作就是一个可以添加到任意数量的菜单和工具栏上的项

QAction *action = new QAction("&new", this);
// 设置图标
action->setIcon(QIcon());
// 状态提示
action->setStatusTip("");
// 设置快捷键
action->setShortcut(QKeySequence::New);
// 设置可见性
action->setVisable(bool);
// 提供“动作”是否为复选动作,QAction默认是没有setCheckable
action->setCheckable(bool);
1
2
3
4
5
6
7
8
9
10
11

signals:

// 被触发
void triggered();
1
2

# QTableView

// 控制视图中数据项之间是否显示网格
QTableView::showGrid();
1
2

# QTableWidget

auto table = QTableWidget(1,3,this);
1

signals:

slots:

// 去除QTableWidget组件中的线
setShowGrid();
setCurrentCell();
// 将表的项原型设置为指定的项。
//当表小部件需要创建一个新的表项时,它将使用项原型克隆函数。例如,当用户在空单元格中进行编辑时。
//当你有一个QTableWidgetItem子类并且想要确保QTableWidget创建你的子类的实例时,这是很有用的。
//表格拥有原型的所有权。
void QTableWidget::setItemPrototype(const QTableWidgetItem *item);
// 设置视图操作的选择模式
//         NoSelection, item 无法被选择
//        SingleSelection,当用户选择一个项目时,任何已经选择的项目都变为未选择。用户可以在单击所选项时按Ctrl键取消所选项。
//        MultiSelection, 当用户以通常的方式选择一个项目时,该项目的选择状态被切换,而其他项目保持不变。可以通过将鼠标拖动到多个项目上来切换它们。
//        ExtendedSelection, 当用户以通常的方式选择一个项目时,选中的项目将被清除,新项目将被选中。但是,如果用户在单击项时按下Ctrl键,则被单击的项被切换,而所有其他项保持不变。如果用户在单击项时按Shift键,则当前项和所单击项之间的所有项都被选中或未选中,具体取决于所单击项的状态。可以通过将鼠标拖动到多个项目上来选择它们。
//        ContiguousSelection 当用户以通常的方式选择一个项目时,选中的项目将被清除,新项目将被选中。但是,如果用户在单击项时按Shift键,则当前项和所单击项之间的所有项都将被选中或未选中,具体取决于所单击项的状态。
setSelectionMode();
// 将此表模型中的行数设置为 rows。如果该值小于rowCount(),则丢弃不需要的行中的数据。
setRowCount(int rows);
// 设置列数
setColumnCount(cols);
// 将水平表头的第 i 个项设置为 item。
setHorizontalHeaderItem(num, item);
// 设置默认选中的单元格
setCurrentCell(row, col);
// 返回指定的 item 或 nullptr
QTableWidgetItem * item = item(row, col);
// 将给定行和列的项设置为item。
// 表获得项的所有权。
// 注意,如果启用了排序(请参阅sortingEnabled)并且column是当前排序列,则该行将被移动到由item确定的排序位置。
//如果你想设置特定行的几个项(比如,通过在循环中调用setItem()),你可能想在这样做之前关闭排序,然后再打开它;这将允许您对同一行中的所有项使用相同的row参数(即setItem()不会移动该行)。
void QTableWidget::setItem(int row, int column, QTableWidgetItem *item);

// 返回当前是第几列
currentColumn();
// 返回当前是低级行
currentRow();
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

signals:

// 窗口部件被改变
QTableWidget::ItemChanged(QTableWidgetItem *);
1
2

slots:

// 清空QWidgetWidget的全部内容,尺寸保持不变,包括表头内容 和选项,清空完之后表头内容会默认成为1,2,3,4之类。
clear();
// 从视图中删除标题之外的所有项。这也将删除所有选择。表的尺寸保持不变。
clearContents();
1
2
3
4

# QAbstractItemView

QAbstractItemView类是每个使用QAbstractItemModel的标准视图的基类。 QAbstractItemView是 一个抽象类,本身不能被实例化。 它提供了一个通过信号和插槽机制与模型进行互操作的标准接口, 使得子类能够随着模型的变化而保持最新。 该类为键盘和鼠标导航,视口滚动,项目编辑和选择提供标准支持。

# QTableWidgetItem

数据类,当用户在空单元格内输入一些文本的时候,QTableWidget 会自动创建一个 QTableWidgetItem 用来存储这些文本。

auto item = new QTableWidgetItem;
// 单元格中写入文本
item->setText(str);
// 将给定角色的项数据设置为指定值
item->setData(int role, QVariant &variant);
// 返回给定角色的项数据
QVariant v = item->data(int role);
1
2
3
4
5
6
7

signals:


1

# QTableWidgetSelectionRange

# QCoreApplication

提供了有关当前运行程序的相关信息,当前程序应是非 GUI 程序。

负责管理 main 时间循环,包含了来自 OS 的所有事件,此外也负责管理程序的初始化和收尾工作,包括系统和应用两方面的设置。

# QGuiApplication

当前程序应该是 GUI 程序。

# QApplication

当前程序采用了 QtWidget 模块就应使用 QApplication。

QApplication app(argc, argv);
app.exec();
1
2

slots:

// 关闭所有窗口
closeAllWindows();
// 关于 Qt
aboutQt();
// 退出应用程序
quit();
1
2
3
4
5
6

# QMenu

菜单

QMenu *menu = menuBar()->addMenu();
// 添加动作
menu->addAction(xx);
// 添加分隔符
QAction *sepator = menu->addSeparator();
1
2
3
4
5

# QMenuBar

菜单栏

// 添加菜单
QMenu *menu = menuBar->addMenu();
1
2

# QDialogButtonBox

多按钮控件

auto buttonBox = new QDialogButtonBox;
// 返回 ok 按钮
auto button = buttonBox(QDialogButtonBox::OK);
1
2
3

# QStatusBar

// 第一次调用会创建状态栏
QStatusBar *bar =  QMainWindow::statusBar();
// 随着状态栏的增长和收缩,stretch参数用于计算给定小部件的合适大小
// 若部件的拉伸因子大于0,则按照拉伸因子的比例分配空间
// 伸展因子默认为 0,即给部件一个最小的空间
// 若部件的大小策略为Fixed,则即使设置了拉伸因子,该部件也不会被拉伸。
// 被添加到状态栏的对象会自动重定义父对象
void QStatusBar::addWidget(QWidget *widget, int stretch = 0)
// 设置标签的文本缩进,偏移量
setIndent(int);
1
2
3
4
5
6
7
8
9
10

# QString

Qt的QString类提供了很方便的对字符串操作的接口,QString没有继承任何Qt基类。

QString str;
// 构造函数
QString(QChar ch);

// int 类型转成 QString
QString::number(int);
// 返回一个此字符串的包含n个字符的字符串,从指定的位置索引开始
// 如果n为-1(默认值),则该函数返回从指定位置开始可用的所有字符。
mid(position, n = -1);
// Returns a string that contains n characters of this string, starting at position pos.
// 比 mid 更快
QString QString::sliced(qsizetype pos, qsizetype n) const
// 如果字符串以s开头则返回true;否则返回false。
// 如果cs为Qt::CaseSensitive(默认值),则搜索区分大小写;否则搜索不区分大小写。
bool QString::startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
// 用之后的字符串替换之前出现的每个字符串,并返回对该字符串的引用。
// 如果 cs 为 Qt::CaseSensitive (默认值),则搜索区分大小写;否则搜索不区分大小写。
QString &replace(const QString &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive)
// 字符串添加字符
str.append(char);
// 将 字符串转为浮点数
str.toDouble(&ok);

QString str=QString( "%1 %2 %3 %4" ).arg( "A" ).arg( "B" ).arg( "C" ).arg( "D" );
//str=="A B C D"
QString str = QString( "%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11" ).
             arg( "1" , "2" , "3" , "4" , "w" , "6" , "7" , "8" , "9" ).arg( "a" , "b" );
//输出为:
// "1 2 3 4 5 6 7 8 9 a b"

// 截取字符串
str.left(str.size() - 1);
// 比较字符串内字符是否相等
if(str.compare(QString::fromLocal8Bit("ssssfdsf") == 0))
{

}

QString::compare("ab","ab");  //值为0;
//QString::compare(“ab”,“df");  //值为<0;
// QString  转 char
str.toLatin1();
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

# QChar

QChar::Null 0x0000A QChar with this value isNull().
1

# QStringList

QStringList list;

list << "dd" << "ss";
1
2
3

# QSpliter

多个窗口部件一起使用的另一种方法是使用 QSpliter,会在水平方向或者竖直方向上排列它的子窗口部件,用户可以利用切分条控制他们的尺寸大小。

# QicsTable

# QVariant

万能数据类型。

The QVariant class acts like a union for the most common Qt data types.

使用实例:

QVariant variant;
// 如果此变量的存储类型不是QMetaType,则返回true。否则返回false。
variant.isValid();
// 返回存储的对象的元对象类型
variant.metaType();
variant.userType(); // 等同于 variant.metaType().id();
// Returns the name of the type stored in the variant.
// The returned strings describe the C++ datatype used to store the data:
// for example, "QFont", "QString", or "QVariantList". An Invalid variant returns 0.
variant.typeName();
1
2
3
4
5
6
7
8
9
10
QString str("https://itzhai.cn");
QVariant var;
var.setValue(str);

QString varStr = var.toString();
qDebug() << "varStr: " << varStr;

QList<QString> list = {"chiyuba.com", "itzhai.cn"};
QVariant var;
var.setValue(list);

QList<QString> varList = var.value<QList<QString> >();
qDebug() << varList;


// 定义结构体
typedef struct myCus {
     QList<QTreeWidgetItem *> lists;
     QList<int> list2;
} MyCus;

// 注册自定义类型
Q_DECLARE_METATYPE(MyCus);

  // 使用自定义类型
MyCus my;
my.list2 = {0, 1};
QVariant var;
var.setValue(my);
MyCus m = var.value<MyCus>();
qDebug() << m.list2;
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

# QMetaType

管理元对象系统中的命名类型。

int id() const
const char *name() const
1
2

# QByteArray

Qt的QByteArray类提供了很方便的对字节流操作的接口,QByteArray没有继承任何Qt基类。

QByteArray可以看做是c语言中char*的升级版本。

// 构造空对象, 里边没有数据
		QByteArray::QByteArray();
		// 将data中的size个字符进行构造, 得到一个字节数组对象
		// 如果 size==-1 函数内部自动计算字符串长度, 计算方式为: strlen(data)
		QByteArray::QByteArray(const char *data, int size = -1);
		// 构造一个长度为size个字节, 并且每个字节值都为ch的字节数组
		QByteArray::QByteArray(int size, char ch);
1
2
3
4
5
6
7

# QNetworkRequest

QNetworkRequest req(QUrl::fromUserInput(QString("%1/api/software/feedback/create").arg(HsrCore::HSR_BASE_URL)));
// 设置原始标头
req.setRawHeader("Accept", "application/json");
req.setRawHeader("Content-Type", "application/json");
req.setRawHeader("X-Token", "xxxx这里是你的tokenxxxxxx");
// 设置请求 url
req.setUrl(qstr);

1
2
3
4
5
6
7
8

# QNetworkReply

// 读取
QByteArray bytes = reply->readAll();
1
2

# QNetworkAccessManager

auto manager = new QNetworkAccessManager(this);
// 发送请求
manager->post(req, body);
1
2
3

# QEventLoop

Qt 常用鼠标事件(QMouseEvent)、键盘事件(QKeyEvent)、绘制事件(QPaintEvent)、 窗口尺寸改变(QResizeEvent)、滚动事件(QScrollEvent)、控件显示(QShowEvent)、 控件隐藏(QHideEvent)、定时器事件(QTimerEvent)。

事件循环类

其中exec是启动事件循环,调用exec以后,调用exec的函数就会被“阻塞”,直到EventLoop里面的while循环结束。

在事件循环中, 不停地去获取下一个事件,然后做出处理。直到quit事件发生,循环结束。

如 Application类中,除去启动参数、版本等相关东西后,关键就是维护了一个QEventLoop,Application的exec就是QEventLoop的exec。

不过Application中的这个EventLoop,我们称作“主事件循环”Main EventLoop。

所有的事件分发、事件处理都从这里开始。

auto eventLoop = QEventLoop;
int exec(QEventLoop::ProcessEventsFlags flags = AllEvents)
void exit(int returnCode = 0)
bool isRunning() const
bool processEvents(QEventLoop::ProcessEventsFlags flags = AllEvents)
void processEvents(QEventLoop::ProcessEventsFlags flags, int maxTime)
void wakeUp()

//程序在exec()里面无限循环,能让跟在exec()后面的代码得不到运行机会,直至程序从exec()跳出。
// 从exec()跳出时,事件循环即被终止。QEventLoop::quit()能够终止事件循环。

// 事件循环实际上类似于一个事件队列,对列入的事件依次的进行处理,当时间做完而时间循环没有结束
// 的时候,其实际上比较类似于一个不占用CPU事件的for(;;)循环。
// 其本质实际上是以队列的方式来重新分配时间片。

// 使用场景1 :模拟同步
bool login(const QString &userName, const QString &passwdHash, const QString &slat)
{
    //声明本地EventLoop
    QEventLoop loop;
    bool result = false;
    //先连接好信号
    connect(&network, &Network::result, [&](bool r, const QString &info){
        result = r;
        qDebug() << info;
        //槽中退出事件循环
        loop.quit();
    });
    //发起登录请求
    sendLoginRequest(userName, passwdHash, slat);
    //启动事件循环。阻塞当前函数调用,但是事件循环还能运行。
    //这里不会再往下运行,直到前面的槽中,调用loop.quit之后,才会继续往下走
    loop.exec();
    //返回result。loop退出之前,result中的值已经被更新了。
    return result;
}
// 使用场景2
// processEvents不阻塞UI
// UI界面,要持续不断地刷新(对于QWidget就是触发paintEvent事件),以保证显示流畅、能及时响应用户输入。
// 一般要有一个良好的帧率,比如每秒刷新60帧, 即经常说的FPS 60, 换算一下 1000 ms/ 60 ≈ 16 ms,也就是每隔16毫秒刷新一次。
// 而我们有时候又需要做一些复杂的计算,这些计算的耗时远远超过了16毫秒。
// 在没有计算完成之前,函数不会退出(相当于阻塞),事件循环得不到及时处理,就会发生UI卡住的现象。
//这种场景下,就可以使用Qt为我们提供的接口,立即处理一次事件循环,来保证UI的流畅
//耗时操作
someWork1()
//适当的位置,插入一个processEvents,保证事件循环被处理
QCoreApplication::processEvents();

//耗时操作
someWork2()
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

slots:

// 接收 http 请求的回复
QNetworkAccessManager::finished(QNetworkReply *reply);
1
2

# QJsonDocument

封装了一个完整的JSON文档,并且可以从UTF-8编码的基于文本的表示以及Qt自己的二进制格式读取和写入该文档。

// 把 json 解析成 UTF-8 编码的 QJsonDocument
[static] QJsonDocument QJsonDocument::fromJson(const QByteArray &json, QJsonParseError *error = nullptr);


QJsonParseError jsonError;
QJsonDocument document = QJsonDocument::fromJson(bytes, &jsonError);
if (jsonError.error != QJsonParseError::NoError) {
    qDebug() << QStringLiteral("解析Json失败");
    return;
}

// 将 JsonDocument 转成 json 字符数组
bytes = document.toJson();
// document 内存储的是否包含 json 对象
bool ok = document.isObject();
// 设置 json 对象
document.setObject(jsonObj);
// 返回 JsonDocumen 中的 JsonObject
document.object();


//将文档对象转换为json数组/对象
//判断文档对象中存储的数据是不是数组
bool QJsonDocument::isArray() const;
// 判断文档对象中存储的数据是不是json对象
bool QJsonDocument::isObject() const
// 文档对象中的数据转换为json对象
QJsonObject QJsonDocument::object() const;
// 文档对象中的数据转换为json数组
QJsonArray QJsonDocument::array() const;
//通过调用QJsonArray , QJsonObject类提供的API读出存储在对象中的数据

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

# QJsonObject

JSON对象是键值对的列表,其中键是唯一的字符串,值由QJsonValue表示。

// 添加键值对
insert(const QString &key, const QJsonValue &value);
// 通过 key 获取 value
value(const QString &key) const;    // utf8
operator[](const QString &key) const;
// 删除并返回 key 对应的 value
take(const QString &key);
// 删除键值对
remove(const QString &key);
// 查找
bool contains(const QString &key) const;
// 通过 key 修改 value
operator[](const QString &key)
obj[key] = value;
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# QJsonValue

该类封装了JSON支持的数据类型

布尔类型:QJsonValue::Bool

浮点类型(包括整形): QJsonValue::Double

字符串类型: QJsonValue::String

Json数组类型: QJsonValue::Array

Json对象类型:QJsonValue::Object

空值类型: QJsonValue::Null

// 是否是Json数组
bool isArray() const;
// 是否是Json对象
bool isObject() const;
// 是否是布尔类型
bool isBool() const;
// 是否是浮点类型(整形也是通过该函数判断)
bool isDouble() const;
// 是否是空值类型
bool isNull() const;
// 是否是字符串类型
bool isString() const;
// 是否是未定义类型(无法识别的类型)
bool isUndefined() const;
// 转换为Json数组
QJsonArray toArray(const QJsonArray &defaultValue) const;
QJsonArray toArray() const;
// 转换为布尔类型
bool toBool(bool defaultValue = false) const;
// 转换为浮点类型
double toDouble(double defaultValue = 0) const;
// 转换为整形
int toInt(int defaultValue = 0) const;
// 转换为Json对象
QJsonObject toObject(const QJsonObject &defaultValue) const;
QJsonObject toObject() const;
// 转换为字符串类型
QString toString() const;
QString toString(const QString &defaultValue) const;

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

# QJsonArray

//QJsonArray封装了Json中的数组
//创建空的Json数组
QJsonArray::QJsonArray();
void QJsonArray::append(const QJsonValue &value);	// 在尾部追加
void QJsonArray::insert(int i, const QJsonValue &value); // 插入到 i 的位置之前
iterator QJsonArray::insert(iterator before, const QJsonValue &value);
void QJsonArray::prepend(const QJsonValue &value); // 添加到数组头部
void QJsonArray::push_back(const QJsonValue &value); // 添加到尾部
void QJsonArray::push_front(const QJsonValue &value); // 添加到头部
//计算数组元素的个数
int QJsonArray::count() const;
int QJsonArray::size() const;
//从数组中取出某一个元素的值
QJsonValue QJsonArray::at(int i) const;
QJsonValue QJsonArray::first() const; // 头部元素
QJsonValue QJsonArray::last() const;  // 尾部元素
QJsonValueRef QJsonArray::operator[](int i);
//删除数组中的某一个元素
iterator QJsonArray::erase(iterator it); // 基于迭代器删除
void QJsonArray::pop_back();             // 删除尾部
void QJsonArray::pop_front();            // 删除头部
void QJsonArray::removeAt(int i);        // 删除i位置的元素
void QJsonArray::removeFirst();          // 删除头部
void QJsonArray::removeLast();           // 删除尾部
QJsonValue QJsonArray::takeAt(int i);    // 删除i位置的原始, 并返回删除的元素的值

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

# QImage

QImage是Qt中用于处理图像的类。它提供了创建、加载、保存、修改和显示图像的功能。QImage支持多种图像格式,并提供了各种图像操作和转换的方法。

load(const QString &fileName, const char *format = nullptr);    // 从文件加载图像。
save(const QString &fileName, const char *format = nullptr, int quality = -1) const;    //将图像保存到文件。
width() const;// 返回图像的宽度(单位为像素)。
height() const;// 返回图像的高度(单位为像素)。
size() const;// 返回图像的尺寸,以QSize对象表示。
pixel(int x, int y) const; //返回指定坐标处的像素值。
setPixel(int x, int y, uint index_or_rgb);// 设置指定坐标处的像素值。
fill(const QColor &color);// 填充整个图像区域。
copy(const QRect &rectangle) const; //复制指定矩形区域的图像副本。
convertToFormat(QImage::Format format, Qt::ImageConversionFlags flags = Qt::AutoColor) const;// 将图像转换为指定的图像格式。
mirrored(bool horizontal = false, bool vertical = false) const;// 返回图像的水平或垂直镜像副本。
// 缩放图像
QImage scaledImage = image.scaled(640, 480);
// 旋转图像
QImage rotatedImage = image.rotated(90);
// 灰度化图像
QImage grayImage = image.convertToFormat(QImage::Format_Grayscale8);
// 二值化图像
QImage binaryImage = grayImage;
binaryImage.threshold(128);
// 从 QByteArray 中加载图像
QImage image;
image.loadFromData(data);

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

# QTcpServer

//构造函数
QTcpServer::QTcpServer(QObject *parent = Q_NULLPTR);
//给监听的套接字设置监听
/*
address:通过类 QHostAddress 可以封装 IPv4、IPv6 格式的 IP 地址,QHostAddress::Any 表示自动绑定
port:如果指定为 0 表示随机绑定一个可用端口
返回值:绑定成功返回 true,失败返回 false
*/
bool QTcpServer::listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);
// 判断当前对象是否在监听, 是返回true,没有监听返回false
bool QTcpServer::isListening() const;
// 如果当前对象正在监听返回监听的服务器地址信息, 否则返回 QHostAddress::Null
QHostAddress QTcpServer::serverAddress() const;
// 如果服务器正在侦听连接,则返回服务器的端口; 否则返回0
quint16 QTcpServer::serverPort() const
//得到和客户端建立连接之后用于通信的QTcpSocket套接字对象,它是QTcpServer的一个子对象,当QTcpServer对象析构的时候会自动析构这个子对象,
//当然也可自己手动析构,建议用完之后自己手动析构这个通信的QTcpSocket对象
QTcpSocket *QTcpServer::nextPendingConnection();
//阻塞等待客户端发起的连接请求,不推荐在单线程程序中使用,建议使用非阻塞方式处理新连接,即使用信号newConnection()
//msec:指定阻塞的最大时长,单位为毫秒(ms)
//timeout:传出参数,如果操作超时timeout为true,没有超时timeout为false
bool QTcpServer::waitForNewConnection(int msec = 0, bool *timedOut = Q_NULLPTR);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

signals:

	//当接受新连接导致错误时,将发射如下信号。socketError参数描述了发生的错误相关的信息
	[signal] void QTcpServer::acceptError(QAbstractSocket::SocketError socketError);
    //每次有新连接可用时都会发出newConnection()信号
	[signal] void QTcpServer::newConnection();
1
2
3
4

# QTcpSocket

//构造函数
QTcpSocket::QTcpSocket(QObject *parent = Q_NULLPTR);
//连接服务器,需要指定服务器端绑定的IP和端口信息
[virtual] void QAbstractSocket::connectToHost(const QString &hostName, quint16 port, OpenMode openMode = ReadWrite, NetworkLayerProtocol protocol = AnyIPProtocol);
[virtual] void QAbstractSocket::connectToHost(const QHostAddress &address, quint16 port, OpenMode openMode = ReadWrite);
//接收数据
//指定可接收的最大字节数 maxSize 的数据到指针 data 指向的内存中
qint64 QIODevice::read(char *data, qint64 maxSize);
//指定可接收的最大字节数 maxSize,返回接收的字符串
QByteArray QIODevice::read(qint64 maxSize);
//将当前可用操作数据全部读出,通过返回值返回读出的字符串
QByteArray QIODevice::readAll();
//发送数据
//发送指针 data 指向的内存中的 maxSize 个字节的数据
qint64 QIODevice::write(const char *data, qint64 maxSize);
//发送指针 data 指向的内存中的数据,字符串以 \0 作为结束标记
qint64 QIODevice::write(const char *data);
//发送参数指定的字符串
qint64 QIODevice::write(const QByteArray &byteArray);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

signals:

//在使用QTcpSocket进行套接字通信的过程中,如果该类对象发射出readyRead()信号,说明对端发送的数据达到了,之后就可以调用read函数接收数据了
[signal] void QIODevice::readyRead();
//调用connectToHost()函数并成功建立连接之后发出connected()信号
[signal] void QAbstractSocket::connected();
//在套接字断开连接时发出disconnected()信号
[signal] void QAbstractSocket::disconnected();
1
2
3
4
5
6

# QDebug

类似 std::cout,用来打印调试信息。

添加 DEFINES += QT_NO_DEBUG_OUTPUT 宏屏蔽 qDebug()。

// 可以打印 Qt 中的基本类型,如 QString,QByteArray,QDate,QRectF,QFont 等
// QMetaType 基本类型

#include <QDebug>
QString str = "333";
qDebug()<< str;
int num = 20;
char str[20]="hello world";
qDebug("如果只写在括号里,是不需要QDebug头文件的 %d %s", num, str);

// 为 自定义类添加 去Debug() 打印支持
#include <QDebug>
class Student
{
public:
    Student(const QString& nm){name = nm;}
    QString getName() const{return name;}
private:
    QString name;
};
QDebug operator<<(QDebug debug, const Student &c)
{
    debug << c.getName();
    return debug;
}
int main(int argc, char *argv[])
{
    Student student("John");
    qDebug() << student;
}
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

# 其他

  • 槽函数大多使用 void 作为返回值,但是槽函数也可以有其他返回值,只是作为槽函数的时候会忽略这些返回值。
Qt::CaseSensitivity 枚举 可取值
        Qt::CaseSensitive 灵敏
        Qt::CaseInsensitive, 不灵敏
例如:void findPrevious(const QString &str,Qt::CaseSensitivity cs);

这个函数想要带一个const QString &str字符串参数,而后面跟的Qt::CaseSensitivity cs则是指示输入的大小写是否要敏感。

Qt::Key 按键

QEvent::event 事件

QDialog::Accepted 1
QDialog::Rejected 0
QDialogButtonBox::Ok

QKeySenquence::New Ctrl + n
// 在可用空间里水平居中
Qt::AlignHCenter


//------ Qt::ItemDataRole
Qt::EditRole            适合在编辑器中编辑的表单中的数据。(QString)
Qt::DisplayRole         要以文本形式呈现的关键数据。(QString)
Qt::UserRole            可用于特定于应用程序的目的的第一个角色。
Qt::TextAlignmentRole   使用默认委托呈现的项的文本对齐方式。
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
最后更新: 2023/9/4 17:01:50