Qt开发学习笔记03

Qt ping Ip端口

在Qt中,可以使用QTcpSocket类来进行Ping操作,同时可以使用connect函数来连接IP地址和端口号。以下是简单的示例代码:

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

int main(int argc, char *argv[])
{
QTcpSocket socket;
socket.connectToHost("127.0.0.1", 80); // 连接IP地址和端口号,这里是本地主机和80端口
if(socket.waitForConnected()) // 等待连接成功
{
qDebug() << "Ping successful!";
}
else
{
qDebug() << "Ping failed!";
}
return 0;
}

需要注意的是,在连接成功之前需要使用waitForConnected函数来等待连接成功,如果连接超时或者出现错误,则连接失败。另外,可以根据需要设置连接超时时间和重试次数等参数来优化Ping操作的效率。

Qt 设置按钮的被按下状态

在Qt中,你可以使用QSS(Qt样式表)来设置按钮的不同状态样式,包括被按下状态。以下是使用QSS设置按钮按下状态的示例:

1
2
3
4
5
6
7
8
9
QPushButton {
/* 设置按钮的默认样式 */
}

QPushButton:pressed {
/* 设置按钮被按下时的样式 */
background-color: #ff0000;
/* 其他样式设置 */
}

在上面的示例中,QPushButton选择器用于设置按钮的默认样式,QPushButton:pressed选择器用于设置按钮被按下时的样式。你可以根据需求在选择器中添加其他样式属性。

要将QSS样式应用于按钮,可以使用setStyleSheet函数。例如:

1
2
QPushButton *button = new QPushButton("按钮");
button->setStyleSheet("QPushButton { /* 按钮的默认样式 */ } QPushButton:pressed { /* 按钮被按下时的样式 */ }");

这样,按钮在被按下时就会显示设置的样式。

Qt 消息提示

在Qt中,可以使用QMessageBox来实现消息提示的功能。QMessageBox是一个用于显示消息对话框的类,它提供了多种类型的消息框,例如信息框、警告框、错误框等。

以下是一个简单的示例代码,演示如何在Qt中使用QMessageBox进行消息提示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <QApplication>
#include <QMessageBox>

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

// 显示一个普通的信息框
QMessageBox::information(nullptr, "提示", "这是一个普通的消息提示框");

// 显示一个警告框
QMessageBox::warning(nullptr, "警告", "这是一个警告消息框");

// 显示一个错误框
QMessageBox::critical(nullptr, "错误", "这是一个错误消息框");

return app.exec();
}

在上述代码中,我们通过调用QMessageBox的静态函数来创建不同类型的消息框。这些函数接受三个参数:父窗口指针、标题和消息文本。其中,第一个参数为nullptr表示消息框没有父窗口,第二个参数是消息框的标题,第三个参数是消息框的内容。

你可以根据需要选择合适的消息框类型,例如information()用于显示信息框,warning()用于显示警告框,critical()用于显示错误框等。

运行上述示例代码,将会依次弹出三个消息框,分别是普通的信息框、警告框和错误框。用户可以点击消息框上的按钮进行相应操作。

Qt tr含数据库查出来的字符串可以翻译吗

是的,你可以使用tr()函数来翻译从数据库中查询出来的字符串。在Qt中,tr()函数不仅可以用于翻译常量字符串,还可以翻译动态生成的字符串。

如果你从数据库中检索到一些字符串,并且希望将它们翻译成其他语言,可以将这些字符串作为参数传递给tr()函数。以下是一个示例:

1
2
QString name = query.value("name").toString();  // 假设从数据库中获取到了名字字段的值
QString translatedName = tr(name.toUtf8().constData());

在上面的示例中,我们将从数据库中获取到的名字字段的值存储在name变量中。然后,我们通过将其转换为UTF-8编码的const char*类型,并将其作为参数传递给tr()函数来进行翻译。翻译后的结果将存储在translatedName变量中。

要使这种方式的翻译生效,你需要确保已经提取了相应的字符串并将其添加到翻译文件(.ts文件)中。然后,你可以使用Qt的翻译工具来翻译这些字符串,并将翻译结果保存到对应的翻译文件中。

请注意,为了能够正确翻译数据库检索出的字符串,确保在查询之前设置了正确的语言环境(例如使用QCoreApplication::setApplicationLanguage())。

希望这个回答对你有帮助!如果你还有其他问题,请随时提问。

Qt C++ 在逻辑中创建一个线程

在Qt中,我们可以通过在逻辑中创建一个QThread对象并使用moveToThread()方法将对象移到新的线程中来创建一个线程。这种方法可以使我们在逻辑层面上更容易地控制线程的生命周期和执行流程。

以下是一个例子,展示了如何在逻辑中创建并控制一个线程:

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

class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = nullptr) : QObject(parent)
{}

public slots:
void doWork()
{
qDebug() << "Worker thread:" << QThread::currentThreadId();
}
};

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

QThread *thread = new QThread();
Worker *worker = new Worker();

worker->moveToThread(thread);

QObject::connect(thread, &QThread::started, worker, &Worker::doWork);

qDebug() << "Main thread:" << QThread::currentThreadId();

thread->start();

return a.exec();
}

在这个例子中,我们创建了一个继承自QObject的Worker类,该类的doWork() 槽函数实现了一个简单的任务。在main()函数中,我们实例化了一个QThread对象,并实例化了一个Worker对象。然后,我们通过worker->moveToThread(thread)方法将Worker对象移动到新的线程中。接着,我们使用connect()方法将线程的started()信号连接到Worker对象的doWork()槽函数,该槽函数在新的线程中执行。

在main()函数中,我们启动了新线程并执行a.exec()函数。在输出中,我们可以看到doWork()槽函数是在新线程中执行的。注意,由于输出是异步进行的,可能会发生输出语句显示顺序不一致的情况。

需要注意的是,线程结束时我们需要手动释放线程对象。在这个例子中,我们可以使用以下代码在线程执行完毕后释放线程对象:

1
QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater);

以上代码会将线程的finished()信号连接到线程的deleteLater()槽函数,并在线程执行完毕后释放线程对象。

Qt C++ 创建多线程

在Qt中,使用QThread类可以创建多个线程。我们可以通过多次实例化线程对象,并调用start()方法启动每个线程。

为了使线程执行有序,我们可以在每个线程中实现不同的任务,并使用QThread的finished()信号来通知其他线程并执行下一步操作。

以下是一个完整的例子,展示了如何创建两个线程并使其有序执行:

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

class ThreadA : public QThread
{
public:
void run() override
{
qDebug() << QString("ThreadA %1: start").arg(QThread::currentThreadId());
sleep(2);
qDebug() << QString("ThreadA %1: end").arg(QThread::currentThreadId());
emit finished();
}
};

class ThreadB : public QThread
{
public:
void run() override
{
qDebug() << QString("ThreadB %1: start").arg(QThread::currentThreadId());
sleep(2);
qDebug() << QString("ThreadB %1: end").arg(QThread::currentThreadId());
emit finished();
}
};

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

ThreadA *threadA = new ThreadA();
ThreadB *threadB = new ThreadB();

// 在线程A执行完毕后启动线程B
QObject::connect(threadA, &ThreadA::finished, threadB, &ThreadB::start);

qDebug() << "main thread: start";

threadA->start();

return a.exec();
}

在这个例子中,我们创建了两个继承自QThread的线程类ThreadA和ThreadB,并在其中实现了不同的任务。我们通过QObject的connect()方法连接了线程A和线程B的finished()信号,在线程A执行完毕后启动线程B。在main()函数中,我们实例化了ThreadA和ThreadB,并启动线程A。线程A执行完毕后,会发出finished()信号,这个信号会被QObject::connect()方法捕获,并启动线程B。

运行这个例子,你会看到线程A和线程B有序地执行了各自的任务,并输出了输出语句。注意,由于输出是异步进行的,可能会发生输出语句显示顺序不一致的情况。

Qt C++ 全局变量map

在Qt C++中,可以使用全局变量来保存和访问数据。然而,由于全局变量可能导致代码的可维护性和可测试性下降,通常不鼓励过多地使用全局变量。

如果您需要在整个应用程序中共享数据,可以考虑使用Singleton模式或者创建一个全局静态类来管理数据。下面是一个示例,展示如何在Qt C++中使用全局变量Map:

首先,在一个头文件(例如global.h)中定义全局变量:

1
2
3
4
5
6
7
8
9
#ifndef GLOBAL_H
#define GLOBAL_H

#include <QMap>

// 全局变量声明
extern QMap<QString, int> globalMap;

#endif // GLOBAL_H

然后,在一个源文件(例如global.cpp)中定义并初始化全局变量:

1
2
3
4
5
6
#include "global.h"

// 全局变量定义
QMap<QString, int> globalMap;

// 在需要的地方使用globalMap

现在,您可以在应用程序的任何地方包含global.h头文件,并使用globalMap变量来保存和访问数据。例如:

1
2
3
4
5
6
7
8
9
10
#include "global.h"

void someFunction()
{
// 向globalMap添加数据
globalMap.insert("Key", 123);

// 从globalMap中获取数据
int value = globalMap.value("Key");
}

请注意,由于全局变量是共享的,多个线程同时访问全局变量可能会导致竞态条件等问题。因此,在多线程环境下,应该采取适当的同步措施来保证全局变量的正确性。

另外,如果您只需要在单个类中使用Map变量,也可以将Map变量作为该类的成员变量进行声明和使用,而无需使用全局变量。

PDF导出

Qt自带导出功能无法支持自动分页,需要自己写分页逻辑,添加页眉页脚也需要自己写逻辑添加,太辣鸡了!

使用默认应用程序打开预览

1
QDesktopServices::openUrl(QUrl::fromLocalFile("4354tq2312.pdf"));

QToolButton 添加下拉选择的样式

创建QToolButton,并添加QMenu

1
2
3
4
5
6
7
8
QToolButton *tBtn = new QToolButton();
tBtn->setText("QToolButton");
tBtn->setPopupMode(QToolButton::MenuButtonPopup);

QMenu *menu = new QMenu();
menu->addAction(tr("切换用户"));
menu->addAction(tr("退出登陆"));
tBtn->setMenu(menu);

修改QToolButton样式如下:

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

QToolButton,QToolButton:unchecked { /* ToolBar里的按钮和带下拉菜单的按钮 */
border: 1px solid transparent;
border-radius: 3px;
background-color: transparent;
margin: 1px;
}
QToolButton:checked{
background-color: #8BF;
border-color: #59F;
}
QToolButton:hover{
background-color: #8BF;
border-color: #59F;
}

QToolButton:pressed,QToolButton:checked:hover{
background-color: #59F;
border-color: #EA2;
}
QToolButton:checked:pressed{
background-color: #8BF;
}

/* only for MenuButtonPopup */
QToolButton[popupMode="1"]{
padding-left: 1px;
padding-right: 15px; /* make way for the popup button */
border: 1px solid #999999;
min-height: 15px;
/*background: qlineargradient(x1:0, y1:0 ,x2:0, y2:1
stop: 0 $grad1a, stop: 0.05 $grad1b, stop: 0.5 $grad1b
stop: 0.95 $grad1a stop: 1$grad1a)*/
}
QToolButton[popupMode="1"]:hover{
background-color: #8BF;
border-color: #59F;
}
QToolButton[popupMode="1"]:pressed{
border-width: 1px;
background-color: #59F;
border-color: #999999;
}
QToolButton::menu-button {
border: 1px solid #999999;
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
width: 16px;
}

修改QMenu样式如下:

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
QMenuBar {
background-color: #FFFFFF;
spacing: 1px;
border-bottom: 1px solid #999999;
}

QMenuBar::item{
background: transparent;
padding: 1px 8px;
}

QMenuBar::item:selected{
background: #8BF;
border: 1px solid #8BF;
}

QMenuBar::item:pressed{
background: #59F;
border: 1px solid #59F;
padding-top: 4px; /*margin-bottom: -4px;*/
}

QMenu {
background-color: #FFFFFF;
border: 1px solid #999999;
margin: 1px; /* some spacing around the menu */
padding: 1px;
}

QMenu::item{
padding: 2px 25px 2px 15px;
border: 1px solid transparent;
margin: 1px;
}
QMenu::icon {/*菜单的图标*/
width: 15px;
height: 15px;
padding:5px;
border-right: 1px inset #999999;
}

QMenu::item:selected {
border-color: #999999;
background: #8BF;
}

QMenu::separator {
height: 1px;
background: #999999;
margin: 0 5px;
}

QMenu::indicator {/*checked 的√*/
width: 13px;
height: 13px;
padding:2px;
}
QMenu::icon:checked { /* appearance of a 'checked' icon */
background: #8BF;
border: 1px inset #59F;
border-radius: 3px;
padding: 2px;
/*position: absolute;
top: 0px;
right: 1px;
bottom: 5px;
left: 2px;*/
}

Qt 对于float类型四舍五入

1.使用QT自带的函数QString::asprintf

1
QString::asprintf("%.2f", 123.12545)  = “123.13”//格式化,自动四舍五入

2.只保留整数位,四舍五入

1
2
float value = 1.237;
int ret = (int)(value + 0.5f);//加 0.5 向下取整

Qt float 四舍五入 保留一位小数

在 Qt 中,要对浮点数进行四舍五入并保留指定小数位数,您可以使用 qRound() 函数结合字符串格式化来实现。

以下是一个示例代码,展示了如何在 Qt 中对浮点数进行四舍五入并保留一位小数:

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

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

float number = 3.14159;
float rounded = qRound(number * 10.0) / 10.0;
QString formatted = QString::number(rounded, 'f', 1);
qDebug() << formatted; // 输出结果: "3.1"

number = 3.69999;
rounded = qRound(number * 10.0) / 10.0;
formatted = QString::number(rounded, 'f', 1);
qDebug() << formatted; // 输出结果: "3.7"

return app.exec();
}

在上述示例中,我们首先将要保留一位小数的浮点数乘以 10(如果保留两位小数,乘以 100。保留N位小数,就是10的N次方),然后使用 qRound() 函数对结果进行四舍五入。接下来,我们再将结果除以 10,以恢复原始的小数位数。最后,我们使用 QString::number() 函数将四舍五入后的浮点数转换为字符串,并指定小数位数为 1。

请注意,由于浮点数的精度限制,进行浮点数运算可能会导致舍入误差。因此,在进行四舍五入操作时,可能会出现微小的误差。如果需要更高精度的计算,可以考虑使用 QDecimal 类型或其他精确计算的解决方案。

使用上述方法可以在 Qt 中对浮点数进行四舍五入并保留指定小数位数。

qRound 的作用

qRound() 是一个 Qt 提供的函数,用于对浮点数进行四舍五入。它的作用是将浮点数转换为最接近的整数。
qRound() 函数遵循标准的四舍五入规则。当小数部分等于 0.5 时,将向最接近的偶数取整。这意味着如果小数部分恰好是 0.5,则结果将是最接近的偶数。例如,2.5 将被四舍五入为 2,而 3.5 将被四舍五入为 4。

银行家舍入法

银行家舍入法(Banker’s rounding)是一种常用的舍入规则,用于在0.5的情况下决定如何进行舍入。它的目标是在进行大量的舍入操作时,尽可能地减少舍入误差的累积。

银行家舍入法的规则如下:

  1. 当小数部分小于0.5时,将其舍弃,不进行舍入。
  2. 当小数部分大于0.5时,将其进位到下一个整数。
  3. 当小数部分等于0.5时,根据整数部分的奇偶性来决定舍入方式:
    • 如果整数部分是偶数,则将小数部分舍弃,不进行舍入。
    • 如果整数部分是奇数,则将小数部分进位到下一个整数。

例如,使用银行家舍入法对2.5进行舍入时,根据规则,应该向最接近的偶数取整。因此,2.5将被舍入为2。

银行家舍入法在一些编程语言和库中被采用,以减少舍入误差的影响。在 Qt 中,默认情况下,qRound() 函数使用银行家舍入法。

需要注意的是,银行家舍入法可能在某些情况下与标准的四舍五入规则有所不同。如果您需要确切地控制舍入方式,请查阅相关文档或参考特定环境的实现规则。

QCombobox设置下拉框的宽度

1
2
3
QComboBox QAbstractItemView {
min-width: 280px;
}

设置最小宽度为280px

QAbstractItemView 是 QComboBox 下拉列表模块的显示,可以单独设置QAbstractItemView 的样式;

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
QComboBox QAbstractItemView {
/* 设置背景颜色 */
background-color: #F0F0F0;
/* 设置文本颜色 */
color: #333333;
/* 设置边框样式 */
border: 1px solid #CCCCCC;
/* 设置边框圆角 */
border-radius: 5px;
/* 设置滚动条样式 */
scrollbar-color: #CCCCCC;
scrollbar-width: 10px;
}

QComboBox QAbstractItemView::item {
/* 设置每个项目的样式 */
background-color: #F0F0F0;
color: #333333;
}

QComboBox QAbstractItemView::item:selected {
/* 设置选中项目的样式 */
background-color: #CCCCCC;
color: #FFFFFF;
}

QComboBox 样式设置

要设置QComboBox的样式,你可以使用Qt的样式表(QSS)或通过编程方式进行设置。以下是一些常见的样式设置示例:

  1. 使用样式表(QSS)设置QComboBox的样式:
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
QComboBox {
/* 设置背景颜色 */
background-color: #F0F0F0;
/* 设置文本颜色 */
color: #333333;
/* 设置边框样式 */
border: 1px solid #CCCCCC;
/* 设置边框圆角 */
border-radius: 5px;
/* 设置下拉箭头样式 */
combobox-popup: 0; /* 禁用默认下拉箭头 */
qproperty-icon: url(:/images/arrow.png); /* 设置自定义下拉箭头图标 */
}

QComboBox::drop-down {
/* 设置下拉箭头样式 */
subcontrol-origin: padding;
subcontrol-position: center right;
width: 20px;
border-left: 1px solid #CCCCCC;
border-radius: 5px;
}

QComboBox::down-arrow {
/* 设置下拉箭头图标 */
image: url(:/images/arrow.png);
}

在上述示例中,我们使用QSS设置了QComboBox的背景颜色、文本颜色、边框样式、边框圆角以及下拉箭头的样式和图标。你可以根据自己的需求进行修改。

  1. 通过编程方式设置QComboBox的样式:
1
2
3
4
5
6
7
8
9
10
11
12
13
QComboBox* comboBox = new QComboBox();

/* 设置背景颜色 */
comboBox->setStyleSheet("background-color: #F0F0F0;");
/* 设置文本颜色 */
comboBox->setStyleSheet("color: #333333;");
/* 设置边框样式 */
comboBox->setStyleSheet("border: 1px solid #CCCCCC;");
/* 设置边框圆角 */
comboBox->setStyleSheet("border-radius: 5px;");
/* 设置下拉箭头样式 */
comboBox->setStyleSheet("combobox-popup: 0;");
comboBox->setStyleSheet("qproperty-icon: url(:/images/arrow.png);");

在上述示例中,我们通过调用QComboBox的setStyleSheet()函数来设置背景颜色、文本颜色、边框样式、边框圆角以及下拉箭头的样式和图标。

请注意,在使用样式表或编程方式设置样式时,你可以根据需要自定义QComboBox的各种属性和子控件的样式。

QObject 强转为 QLineEdit

在Qt中,可以使用qobject_cast来进行QObject到QLineEdit的强制转换。qobject_cast是Qt提供的一个安全的类型转换操作符,用于在运行时检查对象的类型并进行转换。

1
2
// 尝试将QObject对象转换为QLineEdit
QLineEdit* lineEdit = qobject_cast<QLineEdit*>(&obj);

数据曲线

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
// 创建图表视图和图表
QChartView chartView;
QChart *chart = chartView.chart();

// 创建温度和压力的数据系列
QLineSeries *temperatureSeries = new QLineSeries;
QLineSeries *pressureSeries = new QLineSeries;

// 生成随机数据(示例)
QList<QPointF> temperatureData;
QList<QPointF> pressureData;
for (int i = 0; i < 1000; ++i) {
QDateTime dateTime = QDateTime::currentDateTime().addSecs(i * 60); // 使用当前时间加上时间间隔作为时间点
temperatureData.append(QPointF(dateTime.toMSecsSinceEpoch(), qrand() % 100));
pressureData.append(QPointF(dateTime.toMSecsSinceEpoch(), qrand() % 100));
}

// 设置温度和压力的数据
temperatureSeries->replace(temperatureData);
pressureSeries->replace(pressureData);

// 将数据系列添加到图表中
chart->addSeries(temperatureSeries);
chart->addSeries(pressureSeries);

// 设置温度和压力系列的名称
temperatureSeries->setName("温度");
pressureSeries->setName("压力");

// 创建坐标轴
QDateTimeAxis *axisX = new QDateTimeAxis;
QValueAxis *tempAxisY = new QValueAxis;
QValueAxis *pressureAxisY = new QValueAxis;

// 设置坐标轴范围
axisX->setRange(QDateTime::fromMSecsSinceEpoch(temperatureData.first().x()), QDateTime::fromMSecsSinceEpoch(temperatureData.last().x())); // 使用第一个和最后一个时间点作为坐标轴范围
tempAxisY->setRange(0, 45);
pressureAxisY->setRange(0, 100);

// 设置坐标轴标签格式
axisX->setTickCount(10); // 设置刻度数量
axisX->setFormat("hh:mm"); // 根据需要设置日期时间的显示格式

// 将坐标轴添加到图表中
chart->addAxis(axisX, Qt::AlignBottom);
chart->addAxis(tempAxisY, Qt::AlignLeft);
chart->addAxis(pressureAxisY, Qt::AlignLeft);

// 将数据系列与坐标轴关联
temperatureSeries->attachAxis(axisX);
temperatureSeries->attachAxis(tempAxisY);
pressureSeries->attachAxis(axisX);
pressureSeries->attachAxis(pressureAxisY);

// 显示图表视图
chartView.show();

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