Qt开发学习笔记04

Qt C++ 静态全局常量

QStackedWidget为例

在 Qt C++ 中,QStackedWidget 是一个用于管理多个界面堆叠的控件。它可以显示其中一个界面,并允许您在堆栈中切换界面。

如果您想在整个程序中共享一个静态全局常量 QStackedWidget 实例,您可以在全局范围内声明一个指向 QStackedWidget 对象的指针,并在程序的适当位置创建和初始化该对象。

以下是一个示例代码,演示了如何定义和使用静态全局常量 QStackedWidget

1
2
3
4
5
6
7
8
9
10
11
12
13
// 在某个头文件中声明静态全局常量
// header.h
#ifndef HEADER_H
#define HEADER_H

#include <QStackedWidget>

class Globals {
public:
static QStackedWidget* stackedWidget;
};

#endif // HEADER_H
1
2
3
4
5
// 在某个源文件中定义静态全局常量
// source.cpp
#include "header.h"

QStackedWidget* Globals::stackedWidget = nullptr;

在上述示例中,我们在头文件 header.h 中声明了一个名为 Globals 的类,并在其中定义了一个静态指针变量 stackedWidget,其类型为 QStackedWidget*

然后,在源文件 source.cpp 中,我们通过使用 Globals::stackedWidget 来定义和初始化静态全局常量,将其初始值设置为 nullptr

在程序的适当位置(例如 main() 函数或其他初始化代码中),您可以创建一个 QStackedWidget 对象,并将其地址分配给 Globals::stackedWidget,以便在整个程序中共享该对象。

以下是一个简单的示例,演示了如何使用静态全局常量 QStackedWidget

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <QApplication>
#include <QStackedWidget>
#include "header.h"

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

// 创建 QStackedWidget 对象
QStackedWidget stackedWidget;
stackedWidget.addWidget(new QWidget()); // 添加界面部件

// 将 QStackedWidget 对象分配给静态全局常量
Globals::stackedWidget = &stackedWidget;

// 显示主界面
stackedWidget.show();

return app.exec();
}

在上述示例中,我们在 main() 函数中创建了一个 QStackedWidget 对象,并将其地址分配给 Globals::stackedWidget 静态全局常量。然后,我们显示了 stackedWidget,并运行了应用程序的事件循环。

现在,在整个程序的其他地方,您可以通过访问 Globals::stackedWidget 来使用和操作 QStackedWidget 对象。

请注意,静态全局常量的使用需要小心处理,并确保在适当的时间创建和初始化相关对象,以及正确管理对象的生命周期。

查找子窗口并关闭

以 overlayWidget 为例

有两种查找方式:

  • FindDirectChildrenOnly ,只查找直系子节点

    1
    2
    3
    4
    QWidgetList childWidgets = overlayWidget->findChildren<QWidget *>(QString(), Qt::FindDirectChildrenOnly);
    for (QWidget *childWidget : childWidgets) {
    childWidget->close();
    }
  • FindChildrenRecursively ,递归地查找子节点

    1
    2
    3
    4
    QWidgetList childWidgets = overlayWidget->findChildren<QWidget *>(QString(), Qt::FindChildrenRecursively);
    for (QWidget *childWidget : childWidgets) {
    childWidget->close();
    }

如果使用 FindChildrenRecursively 方式,可以写成:

1
2
3
4
QWidgetList childWidgets = overlayWidget->findChildren<QWidget *>();
for (QWidget *childWidget : childWidgets) {
childWidget->close();
}

默认方式为 FindChildrenRecursively

QDialog 的show和exec的区别

在 Qt 中,QDialog 是一个用于显示对话框的类。QDialog 类提供了两种方法来显示对话框:show()exec()。这两种方法有以下区别:

  1. show() 方法:

    • show() 方法是非模态的,即它不会阻塞调用它的线程。调用 show() 后,对话框会立即显示,并且用户可以与其他窗口进行交互。
    • show() 方法返回后,程序将继续执行下面的代码,而不会等待对话框关闭。
    • 对话框的生命周期不受 show() 方法的影响。即使对话框被关闭,它的实例仍然存在,可以重新显示或销毁。
  2. exec() 方法:

    • exec() 方法是模态的,它会阻塞调用它的线程,直到对话框被关闭。
    • 调用 exec() 后,对话框会显示,并且用户只能与对话框进行交互。在对话框被关闭之前,程序不会继续执行下面的代码。
    • exec() 方法返回一个整数值,表示对话框的退出码。如果对话框被关闭,则返回 QDialog::Accepted(接受),否则返回 QDialog::Rejected(拒绝)。

通常情况下,如果您希望对话框以非模态的方式显示,并且希望在对话框显示期间能够与其他部分进行交互,您可以使用 show() 方法。这对于较简单的对话框或在需要对话框的同时执行其他操作的情况很有用。

而如果您需要在对话框关闭之后,继续执行下面的代码,并且需要获取对话框的退出状态,您可以使用 exec() 方法。这对于需要等待用户完成对话框操作后再继续的情况很有用,例如获取对话框中用户的选择或输入。

需要注意的是,对话框可以通过点击关闭按钮、调用 accept()reject() 方法来关闭。在 show() 方法下,对话框关闭后,您可以通过 isVisible() 来检查对话框的可见性。而在 exec() 方法下,可以通过返回的退出码来判断对话框的关闭状态。

Qt isNumber 与 isDigit 区别

在 Qt 中,QString 类提供了两个用于字符判断的函数:isNumber()isDigit()。这两个函数的区别如下:

  1. isNumber() 函数:

    • isNumber() 函数用于判断字符串是否表示一个有效的数字。它会检查字符串中的字符是否组成一个数字,包括正负号、小数点以及科学计数法表示的数字。
    • 如果字符串可以解析为一个有效的数字,isNumber() 函数返回 true,否则返回 false
  2. isDigit() 函数:

    • isDigit() 函数用于判断字符串是否只包含数字字符。它会检查字符串中的每个字符是否是十进制数字(0-9)。
    • 如果字符串中的所有字符都是数字字符,则 isDigit() 函数返回 true,否则返回 false

以下是一个示例代码,演示了 isNumber()isDigit() 函数的用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <QDebug>
#include <QString>

int main() {
QString str1 = "12345";
QString str2 = "3.14";
QString str3 = "-42";
QString str4 = "abc123";

qDebug() << "isNumber()";
qDebug() << str1 << "is a number:" << str1.isNumber();
qDebug() << str2 << "is a number:" << str2.isNumber();
qDebug() << str3 << "is a number:" << str3.isNumber();
qDebug() << str4 << "is a number:" << str4.isNumber();

qDebug() << "isDigit()";
qDebug() << str1 << "contains only digits:" << str1.isDigit();
qDebug() << str2 << "contains only digits:" << str2.isDigit();
qDebug() << str3 << "contains only digits:" << str3.isDigit();
qDebug() << str4 << "contains only digits:" << str4.isDigit();

return 0;
}

运行上述代码,将会输出类似以下内容:

1
2
3
4
5
6
7
8
9
10
isNumber()
"12345" is a number: true
"3.14" is a number: true
"-42" is a number: true
"abc123" is a number: false
isDigit()
"12345" contains only digits: true
"3.14" contains only digits: false
"-42" contains only digits: false
"abc123" contains only digits: false

从输出结果可以看出,isNumber() 函数对于字符串 “12345”、“3.14” 和 “-42” 都返回了 true,因为它们都可以解析为有效的数字。而对于字符串 “abc123”,isNumber() 函数返回了 false,因为它不能解析为有效的数字。

isDigit() 函数对于字符串 “12345” 返回了 true,因为它只包含数字字符。对于字符串 “3.14”、“-42” 和 “abc123”,isDigit() 函数都返回了 false,因为它们中包含了除数字字符外的其他字符。

QChar 类中提供用于判断字符类型的函数

在 Qt 的 QChar 类中,提供了一系列函数用于判断字符的类型。下面是这些函数的详细解释:

  1. isPrint()

    • 用于判断字符是否可打印(即可显示)。这包括空格、数字、字母、标点符号、符号字符等。
    • 如果字符是可打印字符,则返回 true,否则返回 false
  2. isSpace()

    • 用于判断字符是否为空白字符,如空格、制表符、换行符等。
    • 如果字符是空白字符,则返回 true,否则返回 false
  3. isMark()

    • 用于判断字符是否为标记字符。标记字符通常与其他字符组合以形成复合字符。
    • 如果字符是标记字符,则返回 true,否则返回 false
  4. isPunct()

    • 用于判断字符是否为标点符号字符。标点符号通常用于标点、分隔和强调等目的。
    • 如果字符是标点符号字符,则返回 true,否则返回 false
  5. isSymbol()

    • 用于判断字符是否为符号字符。符号字符通常表示特殊符号、货币符号、数学符号等。
    • 如果字符是符号字符,则返回 true,否则返回 false
  6. isLetter()

    • 用于判断字符是否为字母字符。
    • 如果字符是字母字符,则返回 true,否则返回 false
  7. isNumber()

    • 用于判断字符是否为数字字符。
    • 如果字符是数字字符,则返回 true,否则返回 false
  8. isLetterOrNumber()

    • 用于判断字符是否为字母或数字字符。
    • 如果字符是字母或数字字符,则返回 true,否则返回 false
  9. isDigit()

    • 用于判断字符是否为十进制数字字符(0-9)。
    • 如果字符是十进制数字字符,则返回 true,否则返回 false
  10. isLower()

    • 用于判断字符是否为小写字母字符。
    • 如果字符是小写字母字符,则返回 true,否则返回 false
  11. isUpper()

    • 用于判断字符是否为大写字母字符。
    • 如果字符是大写字母字符,则返回 true,否则返回 false
  12. isTitleCase()

    • 用于判断字符是否为标题大小写字母字符。
    • 如果字符是标题大小写字母字符,则返回 true,否则返回 false
  13. isNonCharacter()

    • 用于判断字符是否为非字符。非字符是一些特殊的Unicode代码点,它们被保留作为未来使用或私有用途。
    • 如果字符是非字符,则返回 true,否则返回 false
  14. isHighSurrogate()

    • 用于判断字符是否为高代理项字符。高代理项字符是用于表示Unicode扩展平面字符的一部分。
    • 如果字符是高代理项字符,则返回 true,否则返回 false
  15. isLowSurrogate()

    • 用于判断字符是否为低代理项字符。低代理项字符是用于表示Unicode扩展平面字符的一部分。
    • 如果字符是低代理项字符,则返回 true,否则返回 false
  16. isSurrogate()

    • 用于判断字符是否为代理项字符。代理项字符是由高代理项字符和低代理项字符组成的Unicode扩展平面字符。
    • 如果字符是代理项字符,则返回 true,否则返回 false

这些函数在 QChar 类中可用,可以通过 QChar 对象调用。它们提供了一种方便的方式来判断字符的类型,并根据需要执行相应的操作或逻辑。例如,您可以使用这些函数来验证用户输入、过滤特定类型的字符或执行与字符属性相关的操作。

以下是一个示例代码,演示了如何使用这些函数:

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
#include <QDebug>
#include <QChar>

int main() {
QChar ch1 = 'A';
QChar ch2 = '5';
QChar ch3 = ' ';
QChar ch4 = '@';
QChar ch5 = '\u2070'; // Superscript zero
QChar ch6 = '\uFFFE'; // Non-character

qDebug() << "isPrint():";
qDebug() << ch1 << "is printable:" << ch1.isPrint();
qDebug() << ch2 << "is printable:" << ch2.isPrint();
qDebug() << ch3 << "is printable:" << ch3.isPrint();
qDebug() << ch4 << "is printable:" << ch4.isPrint();
qDebug() << ch5 << "is printable:" << ch5.isPrint();
qDebug() << ch6 << "is printable:" << ch6.isPrint();

qDebug() << "isSpace():";
qDebug() << ch1 << "is space:" << ch1.isSpace();
qDebug() << ch2 << "is space:" << ch2.isSpace();
qDebug() << ch3 << "is space:" << ch3.isSpace();
qDebug() << ch4 << "is space:" << ch4.isSpace();
qDebug() << ch5 << "is space:" << ch5.isSpace();
qDebug() << ch6 << "is space:" << ch6.isSpace();

// ... 继续使用其他函数进行判断和操作

return 0;
}

运行上述代码,将会输出类似以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
isPrint():
'A' is printable: true
'5' is printable: true
' ' is printable: true
'@' is printable: true
'⁰' is printable: true
'￾' is printable: false
isSpace():
'A' is space: false
'5' is space: false
' ' is space: true
'@' is space: false
'⁰' is space: false
'￾' is space: false

从输出结果可以看出,根据字符的不同属性,这些函数返回了相应的结果。您可以根据需要使用这些函数来处理字符。

QString 常用函数

QString 类提供了许多函数来进行字符串操作。以下是 QString 类中的一些常用函数(这里列出的函数不包括静态函数和重载函数):

  1. 构造函数和析构函数:

    • QString(): 默认构造函数,创建一个空字符串。
    • QString(const char *str): 使用 C 风格的字符串构造 QString 对象。
    • QString(const QString &other): 拷贝构造函数。
    • ~QString(): 析构函数。
  2. 字符串操作:

    • append(const QString &str): 在字符串末尾追加另一个字符串。
    • prepend(const QString &str): 在字符串开头插入另一个字符串。
    • insert(int position, const QString &str): 在指定位置插入另一个字符串。
    • remove(int position, int n): 从指定位置开始删除指定数量的字符。
    • replace(int position, int n, const QString &after): 替换指定位置的字符。
    • chop(int n): 删除字符串末尾的指定数量的字符。
    • clear(): 清空字符串。
    • toUpper(): 将字符串转换为大写。
    • toLower(): 将字符串转换为小写。
    • trimmed(): 去除字符串两端的空白字符。
    • simplified(): 去除字符串中多余的空白字符,并将连续的空白字符替换为单个空格。
    • section(const QString &separator, int start, int end): 提取字符串中位于两个分隔符之间的部分。
    • split(const QString &separator, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs): 将字符串拆分为一个字符串列表,根据指定的分隔符进行分割。
    • indexOf(const QString &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive): 查找指定子字符串在字符串中的第一次出现的位置。
    • lastIndexOf(const QString &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive): 查找指定子字符串在字符串中的最后一次出现的位置。
  3. 字符串查询和比较:

    • contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive): 检查字符串是否包含指定的子字符串。
    • startsWith(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive): 检查字符串是否以指定的前缀开始。
    • endsWith(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive): 检查字符串是否以指定的后缀结束。
    • isEmpty(): 检查字符串是否为空。
    • isNull(): 检查字符串是否为 null。
    • length(): 返回字符串的长度。
    • size(): 返回字符串的大小。
  4. 类型转换:

    • toInt(bool *ok = nullptr, int base = 10): 将字符串转换为整数。
    • toDouble(bool *ok = nullptr): 将字符串转换为双精度浮点数。
    • toFloat(bool *ok = nullptr): 将字符串转换为单精度浮点数。
    • toLatin1(): 将字符串转换为 Latin-1 编码。
    • toUtf8(): 将字符串转换为 UTF-8 编码。
  5. 其他:

    • arg(...): 格式化字符串,将占位符替换为指定的参数。
    • mid(int position, int n = -1): 返回从指定位置开始的子字符串。
    • left(int n): 返回字符串的左边 n 个字符。
    • right(int n): 返回字符串的右边 n 个字符。
    • operator=(): 赋值运算符,用于将一个 QString 对象的值赋给另一个 QString 对象。

这只是 QString 类中的一部分常用函数,还有许多其他函数可用于字符串操作。您可以查阅 Qt 文档以获取更详细的信息和更多函数的使用示例。

QLineEdit 去掉鼠标焦点

要在 QLineEdit 中去掉鼠标焦点,您可以调用 clearFocus() 方法来清除当前的焦点。这将导致 QLineEdit 失去焦点,鼠标焦点将转移到其他控件上。

以下是一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <QApplication>
#include <QLineEdit>

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

// 创建 QLineEdit 控件
QLineEdit lineEdit;
lineEdit.setText("Click to focus");

// 设置控件的大小和位置
lineEdit.setGeometry(100, 100, 200, 30);

// 显示控件
lineEdit.show();

// 清除焦点
lineEdit.clearFocus();

return a.exec();
}

在上述示例中,我们创建了一个 QLineEdit 控件,并使用 clearFocus() 方法清除了焦点。这将导致 QLineEdit 失去焦点,从而去掉鼠标焦点。请注意,在调用 clearFocus() 方法之后,QLineEdit 不会自动获取焦点,鼠标焦点将保持在其他控件上。

添加阴影效果

以QDialog 为例

要为 QDialog 添加阴影效果,可以使用 QGraphicsDropShadowEffect 类来实现。以下是一个示例,演示如何使用 QGraphicsDropShadowEffect 为 QDialog 添加阴影效果:

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
#include <QApplication>
#include <QDialog>
#include <QGraphicsDropShadowEffect>

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

// 创建 QDialog 对象
QDialog dialog;

// 创建 QGraphicsDropShadowEffect 对象
QGraphicsDropShadowEffect *shadowEffect = new QGraphicsDropShadowEffect;
shadowEffect->setBlurRadius(10); // 设置阴影模糊半径
shadowEffect->setColor(Qt::black); // 设置阴影颜色
shadowEffect->setOffset(0); // 设置阴影偏移量

// 将 QGraphicsDropShadowEffect 应用于 QDialog
dialog.setGraphicsEffect(shadowEffect);

// 设置对话框的大小和位置
dialog.setGeometry(100, 100, 400, 200);

// 显示对话框
dialog.show();

return a.exec();
}

在上述示例中,我们创建了一个 QDialog 对象,并创建了一个 QGraphicsDropShadowEffect 对象来定义阴影效果的属性。然后,我们使用 setGraphicsEffect() 方法将 QGraphicsDropShadowEffect 应用于 QDialog。通过调整 setBlurRadius()setColor()setOffset() 方法的参数,您可以自定义阴影的模糊半径、颜色和偏移量。

请注意,在使用 QGraphicsDropShadowEffect 时,需要确保包含 QDialog 的窗口部件(例如 QWidget、QMainWindow 等)具有透明背景,以便阴影效果能够正确显示。

运行上述代码将会显示一个带有阴影效果的 QDialog 对话框。您可以根据需要调整 QGraphicsDropShadowEffect 的属性,以实现所需的阴影效果。

QtConcurrent 的异步处理方法

QtConcurrent提供了多种异步处理方法,用于在多线程环境下执行任务。以下是一些常用的异步处理方法:

  1. QtConcurrent::run():该方法可用于在后台线程中执行一个函数。它接受一个函数对象或函数指针作为参数,并返回一个 QFuture 对象,用于跟踪任务的状态和结果。示例代码如下:
1
2
3
4
5
6
7
QFuture<void> future = QtConcurrent::run([](){
// 在后台线程中执行的任务
// ...
});

// 可选:等待任务完成
future.waitForFinished();
  1. QtConcurrent::mapped():该方法用于将输入序列的每个元素映射到一个函数的结果,并返回一个 QFuture 对象,其中包含映射结果的列表。示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
QList<int> inputList = ...; // 输入序列

QFuture<int> future = QtConcurrent::mapped(inputList, [](int value){
// 将每个输入元素映射为结果
// ...
return result;
});

// 可选:等待映射完成
future.waitForFinished();

// 获取映射结果列表
QList<int> mappedResults = future.results();
  1. QtConcurrent::filter():该方法用于过滤输入序列的元素,并返回一个 QFuture 对象,其中包含满足过滤条件的元素列表。示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
QList<int> inputList = ...; // 输入序列

QFuture<int> future = QtConcurrent::filter(inputList, [](int value){
// 返回 true 表示保留元素,返回 false 表示过滤元素
// ...
return condition;
});

// 可选:等待过滤完成
future.waitForFinished();

// 获取过滤结果列表
QList<int> filteredResults = future.results();
  1. QtConcurrent::mappedReduced():该方法用于将输入序列的每个元素映射到一个结果,并将这些结果归约为单个值。它接受一个映射函数和一个归约函数作为参数,并返回一个 QFuture 对象,其中包含归约的结果。示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
QList<int> inputList = ...; // 输入序列

int reducedResult = QtConcurrent::mappedReduced(inputList, [](int value){
// 将每个输入元素映射为结果
// ...
return result;
}, [](int result1, int result2){
// 将两个映射结果归约为单个值
// ...
return reducedResult;
});

// 可选:等待映射和归约完成
QtConcurrent::waitForCompletion(reducedResult);

以上只是一些常用的异步处理方法示例,QtConcurrent还提供其他更多的方法和功能,如 QtConcurrent::mappedReduced()QtConcurrent::mappedReducedBatched()QtConcurrent::mappedReducedIndexed() 等。您可以查阅Qt的官方文档或参考最新的Qt文档,以获取更详细和全面的信息。

IP地址是否能ping通过

  • Linux/macOS

    如果您只需要检测 IP 地址是否能够通过 Ping 命令,可以使用 Qt 的 QProcess 类来执行 Ping 命令并检查返回结果。以下是一个示例方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    QString ipAddress = "192.168.0.100"; // 设置要检测的 IP 地址

    QProcess process;
    QStringList arguments;
    arguments << "-c" << "1" << ipAddress; // 在 Linux/macOS 上使用 "-c" 参数,在 Windows 上使用 "-n" 参数

    #ifdef Q_OS_WIN
    process.start("ping", arguments);
    #else
    process.start("ping", arguments, QIODevice::ReadOnly);
    #endif

    if (process.waitForFinished() && process.exitCode() == 0) {
    // IP 地址可以通过 Ping
    qDebug() << "IP address is reachable";
    } else {
    // IP 地址无法通过 Ping
    qDebug() << "IP address is not reachable";
    }

    在上述示例中,我们使用 QProcess 类来执行 Ping 命令。根据不同的操作系统,设置不同的 Ping 参数(“-c” 在 Linux/macOS 上,“-n” 在 Windows 上)。然后,我们使用 waitForFinished() 等待 Ping 命令执行完成,并通过 exitCode() 检查命令的返回值。如果返回值为 0,表示 IP 地址可以通过 Ping;如果返回值非零,表示 IP 地址无法通过 Ping。

    请注意,上述代码在 Linux 和 macOS 上使用 QIODevice::ReadOnly 作为 start() 函数的第三个参数,以便可以读取 Ping 命令的输出。在 Windows 上,不需要传递该参数。

    需要注意的是,Ping 命令的可用性和结果解释可能会因操作系统和网络环境的不同而有所差异。此方法仅提供了一种使用 Qt 检测 IP 地址是否能够通过 Ping 的示例。

    希望这次的回答能满足您的需求!如果您有任何进一步的问题,请随时提问。

  • Windows

    如果您在 Windows 上使用 Qt,并且只需要检测 IP 地址是否能够通过 Ping 命令,可以使用 QProcess 类来执行 ping 命令并检查返回结果。以下是一个针对 Windows 平台的示例方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    QString ipAddress = "192.168.0.100"; // 设置要检测的 IP 地址

    QProcess process;
    QStringList arguments;
    arguments << "-n" << "1" << ipAddress;

    process.start("ping", arguments);

    if (process.waitForFinished() && process.exitCode() == 0) {
    // IP 地址可以通过 Ping
    qDebug() << "IP address is reachable";
    } else {
    // IP 地址无法通过 Ping
    qDebug() << "IP address is not reachable";
    }

    在上述示例中,我们使用 QProcess 类来执行 ping 命令。我们设置了 "-n" 参数来指定只发送一个 ICMP Echo 请求,并指定要检测的 IP 地址。然后,我们使用 waitForFinished() 函数等待 ping 命令执行完成,并通过 exitCode() 检查命令的返回值。如果返回值为 0,表示 IP 地址可以通过 Ping;如果返回值非零,表示 IP 地址无法通过 Ping。

    请注意,Ping 命令的可用性和结果解释可能会因操作系统和网络环境的不同而有所差异。此方法仅提供了一种使用 Qt 在 Windows 平台上检测 IP 地址是否能够通过 Ping 的示例。

    使用QProcess检测IP会有一个问题,QProcess是阻塞形式的,如果IP不通时,虽然能够检测到,但会使程序卡顿,因为只有检测完成后才能继续程序

QTimer 的setSingleShot 作用是什么

Qt的QTimer类的setSingleShot(true)方法用于将计时器设置为单次触发模式。

当你调用setSingleShot(true)将计时器设置为单次触发模式后,它将在启动后的指定时间间隔后触发一次timeout()信号,然后停止计时器。这意味着计时器只会触发一次,而不是周期性地触发。

以下是一个示例代码,展示了setSingleShot(true)的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <QCoreApplication>
#include <QTimer>
#include <QDebug>

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

QTimer timer;
timer.setSingleShot(true); // 设置为单次触发模式

QObject::connect(&timer, &QTimer::timeout, [](){
qDebug() << "Timer triggered.";
});

timer.start(1000); // 1秒后触发timeout()信号

return a.exec();
}

在上述示例中,我们创建了一个QTimer对象,并通过setSingleShot(true)将其设置为单次触发模式。然后,我们将timer的timeout()信号连接到一个匿名Lambda槽函数,输出一条调试信息。最后,我们通过调用timer.start(1000)启动计时器,并设置触发时间间隔为1秒。

这样,计时器将在启动后的1秒钟内触发timeout()信号,并执行相应的槽函数,然后停止计时器。

Qt在Windows下部署步骤

  1. 在Qt 开发工具下选择 Release 构建,打包
  2. 在某个盘符下新建一个文件夹(例如:在D盘下新建user文件夹)
  3. 在使用 Release 构建打包的文件下的release文件夹下的 .exe文件复制到新建的文件夹下
  4. 找到构建打包的编译器,如果选择的是MinGW 64-bit,就需要在开始菜单里找到MinGW 64-bit命令窗口,点击会弹出命令窗口
  5. 在命令窗口中输入cd /d D:\XXXX (XXXX 是新建文件夹的名称)
  6. 接着在窗口中输入 windeployqt xxxxx.exe (xxxxx 是复制进去的.exe 文件的名称)
  7. 将整个新建的文件夹复制到想要部署的机器中即可;(在生成的文件中,找到.exe文件,可直接运行了)

Qt 使用鼠标或者触摸滑动窗口

以QScrollArea 窗口为例

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
   ui->scrollArea->setFocusPolicy(Qt::NoFocus);

ui->scrollArea->installEventFilter(this);

QScrollerProperties scrollerProps;

// 鼠标按下后,目标收到鼠标按下事件的延迟时间,单位s。如果在延迟时间内开始了拖拽,目标不会收到鼠标事件
scrollerProps.setScrollMetric(QScrollerProperties::MousePressEventDelay, 1);

// 鼠标按下后开始移动到被判定为拖拽操作的距离,单位m
scrollerProps.setScrollMetric(QScrollerProperties::DragStartDistance, 0.003);

// 似乎是影响速度的计算,平滑拖拽到自动滚动的速度
scrollerProps.setScrollMetric(QScrollerProperties::DragVelocitySmoothingFactor, 1);

// 未测试
// scrollerProps.setScrollMetric(QScrollerProperties::AxisLockThreshold, 0.1);

// 滚动曲线和减速影响因子,具体应该配合曲线。因为可以自定义曲线,所以曲线必须构造出QEasingCurve,
scrollerProps.setScrollMetric(QScrollerProperties::ScrollingCurve, QEasingCurve(QEasingCurve::OutQuad));
scrollerProps.setScrollMetric(QScrollerProperties::DecelerationFactor, 0.3);

// 当鼠标抬起后,触发自动滚动的最小速度、以及能达到的最大速度,单位m/s
scrollerProps.setScrollMetric(QScrollerProperties::MinimumVelocity, 0.003);
scrollerProps.setScrollMetric(QScrollerProperties::MaximumVelocity, 1);

// 当鼠标抬起后,点击操作会停止当前滚动,滚动速度超过该速度时,鼠标点击不会传递给目标,单位m/s
scrollerProps.setScrollMetric(QScrollerProperties::MaximumClickThroughVelocity, 0.06);

// 当鼠标抬起后自动滚动,在该时间内的加速滑动手势会加速当前滚动,单位s, 可以设置加速后速度比例,必须大于1
scrollerProps.setScrollMetric(QScrollerProperties::AcceleratingFlickMaximumTime, 2);
scrollerProps.setScrollMetric(QScrollerProperties::AcceleratingFlickSpeedupFactor, 1.5);

// 不是很理解这两个
// scrollerProps.setScrollMetric(QScrollerProperties::SnapPositionRatio, 0.1);
// scrollerProps.setScrollMetric(QScrollerProperties::SnapTime, 4);

scrollerProps.setScrollMetric(QScrollerProperties::OvershootDragResistanceFactor,
0.2); // 过量拖拽时,实际拖拽距离与鼠标移动距离的比例,越小越阻塞,范围0-1
scrollerProps.setScrollMetric(QScrollerProperties::OvershootDragDistanceFactor, 0.5); // 过量拖拽时,最大可拖拽距离占窗口的比例,范围0-1
scrollerProps.setScrollMetric(QScrollerProperties::OvershootScrollDistanceFactor, 0.2); // 允许的自动滚动时的过量滚动比例,同上
scrollerProps.setScrollMetric(QScrollerProperties::OvershootScrollTime, 0.3); // 过量拖拽后释放,恢复到初始状态的时间,单位s

// 设置允许过量拖拽的策略,滚动条出现时开启、始终关闭、始终开启
scrollerProps.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy,
QScrollerProperties::OvershootAlwaysOff);
scrollerProps.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy,
QScrollerProperties::OvershootAlwaysOff);
scrollerProps.setScrollMetric(QScrollerProperties::FrameRate, QScrollerProperties::Fps60);


scroller = QScroller::scroller(ui->scrollArea);

//TouchGesture LeftMouseButtonGesture RightMouseButtonGesture MiddleMouseButtonGesture
scroller->grabGesture(ui->scrollArea, QScroller::LeftMouseButtonGesture);//鼠标左键
scroller->setScrollerProperties(scrollerProps);

Qt输入框 Debug可以显示 Release不显示

是因为在设置 QLineEdit 监听(lineEdit->installEventFilter(this);),在重写监听事件时,未在方法结束后返回数据

1
return QWidget::eventFilter(watched, event);

Qt C++ 简单的加密解密

当然,我可以教你一些简单的加密解密方法,使用Qt C++编写。以下是一个基于简单的替换密码的示例:

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
#include <QtCore>
#include <iostream>

QString encrypt(const QString& plaintext, const QString& key) {
QString ciphertext;
for (const QChar& character : plaintext) {
// 加密算法:将字符替换为密钥中的对应字符
int index = character.unicode() % key.length();
ciphertext.append(key.at(index));
}
return ciphertext;
}

QString decrypt(const QString& ciphertext, const QString& key) {
QString plaintext;
for (const QChar& character : ciphertext) {
// 解密算法:将密文字符在密钥中的索引位置找到对应的原始字符
int index = key.indexOf(character);
plaintext.append(QChar(index));
}
return plaintext;
}

int main() {
QString plaintext = "Hello, World!";
QString key = "abcdefghijklmnopqrstuvwxyz";

QString ciphertext = encrypt(plaintext, key);
QString decryptedText = decrypt(ciphertext, key);

qDebug() << "Plaintext: " << plaintext;
qDebug() << "Ciphertext: " << ciphertext;
qDebug() << "Decrypted Text: " << decryptedText;

return 0;
}

在上面的示例中,我们首先定义了两个函数:encryptdecryptencrypt函数接受明文和密钥作为输入,将明文字符替换为密钥中相应位置的字符,并返回密文。decrypt函数接受密文和密钥作为输入,将密文字符在密钥中的索引位置找到对应的原始字符,并返回明文。

main函数中,我们定义了一个简单的明文和密钥,并使用encrypt函数将明文加密为密文。然后,我们使用decrypt函数将密文解密为明文。最后,我们打印出明文、密文和解密后的文本。

你可以根据需要修改密钥和明文来进行测试。请注意,这只是一个简单的加密解密示例,不适用于安全性要求较高的场景。

progressBar 修改进度颜色

1
2
3
QProgressBar::chunk {
background-color: #ff6348;
}

QString number 方法

QString number(double, char f=‘g’, int prec=6)

QString number(double, char f='g', int prec=6) 函数是 Qt 库中的一个函数,用于将双精度浮点数转换为字符串。

  • double:要转换的双精度浮点数。

  • char f:指定要使用的格式。可以是以下值之一:

    • 'f':固定小数点格式。
    • 'g':通用格式。
    • 'e':科学计数法。
    • 'a':十六进制格式。
  • int prec:要使用的精度。这是要显示的小数位数。

该函数返回一个包含转换后的字符串的 QString 对象。

例如,以下代码将双精度浮点数 3.141592653589793转换为字符串,并使用通用格式和 6 位精度:

1
QString str = QString::number(3.141592653589793, 'g', 6);

这将产生以下字符串:

1
"3.14159"

如果要使用科学计数法,可以将 f 参数设置为 'e'

1
QString str = QString::number(3.141592653589793, 'e', 6);

这将产生以下字符串:

1
"3.141593e+00"

如果要使用十六进制格式,可以将 f 参数设置为 'a'

1
QString str = QString::number(3.141592653589793, 'a', 6);

这将产生以下字符串:

1
"1.921fb54442d18"

QString number() 函数是一个非常灵活的函数,可以用于将双精度浮点数转换为各种不同的格式。

日志如何输出到文件

要使用上述的日志输出函数,您需要将它添加到您的Qt应用程序中的代码中。以下是一个示例,展示了如何在Qt应用程序中使用该日志输出函数:

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
#include <QApplication>
#include <QFile>
#include <QTextStream>
#include <QDebug>

void logMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
QFile file("path/to/log/file.txt");
if (file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
QTextStream stream(&file);

QString logType;
switch (type) {
case QtDebugMsg:
logType = "Debug";
break;
case QtWarningMsg:
logType = "Warning";
break;
case QtCriticalMsg:
logType = "Critical";
break;
case QtFatalMsg:
logType = "Fatal";
break;
}

stream << logType << ": " << msg << " (" << context.file << ":" << context.line << ", " << context.function << ")" << endl;

file.close();
}
}

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

// 设置日志输出函数
qInstallMessageHandler(logMessage);

// ...

// 以下是一些示例日志输出
qDebug() << "This is a debug message.";
qWarning() << "This is a warning message.";
qCritical() << "This is a critical message.";

return app.exec();
}

在上面的示例中,我们将logMessage函数添加到主函数之前,并使用qInstallMessageHandler函数将其设置为Qt的默认消息处理程序。然后,在主函数中,我们使用qDebugqWarningqCritical宏输出一些示例日志消息。这些日志消息将被重定向到指定的日志文件中。

请确保将"path/to/log/file.txt"替换为您希望将日志输出到的实际文件路径。

当您运行该应用程序时,日志消息将被写入指定的日志文件中。

在非GUI线程中创建或操作了QWidge 引发的错误

Widgets must be created in the GUI thread.", file kernel\qwidget.cpp, line 1145

在Qt中,QWidget及其派生类的对象必须在GUI线程中进行创建和操作。

向PDF中插入图片并旋转90度

要在SqlThread::add_widget函数中将绘制的curve_pix旋转90度,你可以使用QTransform类来实现。以下是修改后的代码示例:

1
2
3
4
5
6
7
8
9
10
void SqlThread::add_widget(QPixmap curve_pix) {
curve_pix = curve_pix.scaled(PDFPAGE_WIDTH, curve_pix.height() * PAGE_SCALE_WIDTH,
Qt::IgnoreAspectRatio);

QPixmap rotatedPixmap = curve_pix.transformed(QTransform().rotate(90));

pPainter->drawPixmap(0, TEXT_HEIGHT, rotatedPixmap);
TEXT_HEIGHT += rotatedPixmap.height();
GENERAL_HEIGHT += rotatedPixmap.height();
}

在这个示例中,我们首先对curve_pix进行缩放以适应绘制区域。然后,使用curve_pix.transformed(QTransform().rotate(90))curve_pix旋转90度得到rotatedPixmap。最后,使用pPainter->drawPixmap绘制旋转后的rotatedPixmap

通过这种方式,你可以在SqlThread::add_widget函数中将绘制的curve_pix旋转90度后进行绘制。请注意,在非GUI线程中进行绘制操作时,确保已正确设置绘图设备和绘图上下文。

获取当前服务路径

1
QString currentPath = QDir::currentPath();

QSpinBox 可设置的参数

QSpinBox是Qt框架中的一个小部件,用于显示和编辑整数值。它提供了一些可设置的参数,用于自定义其外观和行为。

以下是一些常用的QSpinBox可设置的参数:

  1. minimum:设置最小值。
  2. maximum:设置最大值。
  3. value:设置当前值。
  4. singleStep:设置单步增加或减少的大小。
  5. prefix:设置显示值前缀。
  6. suffix:设置显示值后缀。
  7. readOnly:设置是否为只读模式。
  8. buttonSymbols:设置按钮的显示样式,可以是QAbstractSpinBox::UpDownArrowsQAbstractSpinBox::PlusMinusQAbstractSpinBox::NoButtons
  9. alignment:设置文本对齐方式,可以是Qt::AlignLeftQt::AlignRightQt::AlignCenter
  10. wrapping:设置是否循环滚动,即当达到最小或最大值时是否回到另一端。
  11. keyboardTracking:设置是否跟踪键盘输入,即在用户输入时是否即时更新值。
  12. specialValueText:设置特殊值的文本表示,特殊值通常用于表示无效或未设置的情况。

你可以使用这些参数来调整QSpinBox的行为和外观,以满足你的需求。可以通过set函数系列来设置这些参数,例如setMinimum()setMaximum()setValue()等。

另外,还可以使用styleSheet属性来设置QSpinBox的样式表,进一步自定义其外观。

将指定文件夹下的文件复制到某个文件夹下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 源文件夹
QString source_dir = "D:/CES/db";

// 选择目标文件夹
QString target_dir = QFileDialog::getExistingDirectory(nullptr, "选择目标文件夹", QDir::homePath());
if (target_dir.isEmpty()) {
qDebug() << "未选择目标文件夹";
return;
}

// 检查目标文件夹是否存在,如果不存在则创建
QDir target_dir_info(target_dir);
if (!target_dir_info.exists()) {
target_dir_info.mkpath(".");
}

// 复制文件
QDir source_dir_info(source_dir);
QStringList files = source_dir_info.entryList(QDir::Files);
for (QString file : files) {
QString source_file = source_dir + "/" + file;
QString target_file = target_dir + "/" + file;
QFile::copy(source_file, target_file);
}

将某个文件复制到指定文件夹下

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
// 源文件(可选)
QString source_file;

// 目标文件夹
QString target_dir = "D:/CES/db";

// 如果源文件为空,则提示用户选择源文件
if (source_file.isEmpty()) {
// 使用 QFileDialog 类让用户选择源文件
QFileDialog file_dialog(nullptr, "选择源文件", "", "数据库文件 (ces.db)");
if (file_dialog.exec() == QFileDialog::Accepted) {
source_file = file_dialog.selectedFiles()[0];
} else {
qDebug() << "用户取消了选择源文件";
return;
}
}

// 检查目标文件夹是否存在,如果不存在则创建
QDir target_dir_info(target_dir);
if (!target_dir_info.exists()) {
target_dir_info.mkpath(".");
}

// 复制文件
QString target_file = target_dir + "/" + QFileInfo(source_file).fileName();
QFile::copy(source_file, target_file);

程序关闭重启

在一个析构函数里添加以下代码

1
2
3
4
QString program = QApplication::applicationFilePath();
QStringList arguments = QApplication::arguments();
// 启动一个新的实例,并关闭当前实例
QProcess::startDetached(program, arguments);

如果需要更新程序删除.exe文件是无法删除的,因为会一直在启动状态,需要执行命令彻底关闭:

taskkill -f -t -im xxx.exe

-------------本文结束感谢您的阅读-------------