Qt开发学习笔记05

QLineEdit不显示和输入的数据

QLineEdit 设置了 installEventFilter 后,不显示QLineEdit 和输入的数据:

是因为 bool eventFilter(QObject *watched, QEvent *event); 方法没有设置返回值导致;

PBS中启动ArcAir校准软件逻辑

是通过执行一个bat脚本文件

脚本中原来的命令是:

1
cmd /k "cd /d C:\ArcAir&&ArcAir.exe" 

cmd /k "cd /d C:\ArcAir&&ArcAir.exe" 是一个 Windows 命令,它将执行以下操作:

  1. 打开一个新的命令提示符窗口。
  2. 将当前目录更改为 C:\ArcAir
  3. C:\ArcAir 目录中运行 ArcAir.exe 可执行文件。

分解:

  • /k:表示在执行完命令后保持命令提示符窗口打开。
  • cd /d C:\ArcAir:将当前目录更改为 C:\ArcAir
  • &&:表示在执行第一个命令(cd /d C:\ArcAir)后,再执行第二个命令(ArcAir.exe)。

因此,此命令的目的是导航到 C:\ArcAir 目录并运行 ArcAir.exe 可执行文件。通常,此命令用于从命令提示符启动 ArcAir 软件。

示例:

假设你有一个名为 ArcAir.exe 的可执行文件位于 C:\ArcAir 目录中。要从命令提示符启动此可执行文件,你可以运行以下命令:

1
cmd /k "cd /d C:\ArcAir&&ArcAir.exe"

这将打开一个新的命令提示符窗口,将当前目录更改为 C:\ArcAir,并运行 ArcAir.exe 可执行文件。

存在一个问题,就是每次打开后无法关闭命令提示符窗口,会一直增加

需要将命令改为:

1
2
start "ArcAir" /d "C:\ArcAir" "ArcAir.exe"
exit

要使用此命令关闭命令提示符窗口,你需要使用 start 命令。start 命令允许你启动一个新进程,并在其完成后自动关闭命令提示符窗口。

因此,你可以使用以下命令来关闭命令提示符窗口:

1
start "ArcAir" /d "C:\ArcAir" "ArcAir.exe"

分解:

  • start:启动一个新进程。
  • "ArcAir":新进程的标题(可选)。
  • /d "C:\ArcAir":新进程的当前目录。
  • "ArcAir.exe":要启动的可执行文件。

示例:

假设你有一个名为 ArcAir.exe 的可执行文件位于 C:\ArcAir 目录中。要从命令提示符启动此可执行文件并在其退出后关闭命令提示符窗口,你可以运行以下命令:

1
start "ArcAir" /d "C:\ArcAir" "ArcAir.exe"

这将打开一个新的命令提示符窗口,将当前目录更改为 C:\ArcAir,并运行 ArcAir.exe 可执行文件。在 ArcAir.exe 退出后,命令提示符窗口将自动关闭。

如何捕捉异常信息

在Qt中,你可以使用C++的异常处理机制来捕获异常信息。Qt本身并没有提供自己的异常处理机制,而是依赖于C++的trycatchthrow来处理异常。

下面是一个简单的示例,展示了如何在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
#include <QCoreApplication>
#include <QDebug>

void process() {
try {
// 可能会抛出异常的代码
throw QString("An exception occurred!");
} catch (const QString& e) {
qDebug() << "Caught exception: " << e;
} catch (...) {
qDebug() << "Caught unknown exception";
}
}

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

try {
process();
} catch (...) {
qDebug() << "Caught exception in main";
}

return app.exec();
}

在上面的示例中,process()函数中包含可能会抛出异常的代码,当抛出异常时,它会被catch块捕获并处理。在main()函数中,我们调用process()函数,并在外部的try块中捕获可能抛出的异常。如果异常未被内部的catch块捕获,外部的catch块会捕获未处理的异常。

请注意,Qt的信号和槽机制通常用于处理事件和通信,而不是用于异常处理。因此,在Qt应用程序中,你可能更倾向于使用Qt的信号和槽机制来处理事件和错误,而不是依赖于异常处理。但是,如果你的应用程序中需要使用异常处理,你仍然可以在Qt中使用C++的异常处理机制。

finally 是 C++20 中引入的一个新特性,因此如果你在较早版本的 C++ 中使用它,则会遇到此错误。

要解决此问题,请确保你使用的是 C++20 或更高版本。你可以在编译器设置中检查 C++ 标准版本。

如果你无法使用 C++20,则可以使用以下代码模拟 finally 块的行为:

1
2
3
4
5
struct Finally {
Finally(std::function<void()> f) : f(f) {}
~Finally() { f(); }
std::function<void()> f;
};

然后,你可以在 try 块中使用 Finally 对象来执行清理操作:

1
2
3
4
5
6
7
8
try {
// 可能引发异常的代码
} catch (...) {
// 处理任何类型的异常
}
Finally finally([] {
// 无论是否发生异常,始终执行的代码
});

这将确保在 try 块或 catch 块中发生异常时始终执行清理操作。

ASSERT failure in QList<T>::take: "index out of range", file D:/install/Qt/Qt5.12.2/5.12.2/mingw73_64/include/QtCore/qli
st.h, line 56

上述异常try-catch无法捕捉

ASSERT 失败并不是通过抛出标准异常来处理的,而是通过断言机制来实现的。当 QList::take 函数发现索引超出范围时,它会触发一个断言失败,而不是抛出一个标准的异常。断言失败会导致程序立即终止,而不会被捕获到 try-catch 块中。要避免断言失败,你应该在调用 QList 的相关函数之前,确保索引值在有效范围内,而不是依赖于 try-catch 块来捕获断言失败。在 Qt 中,断言通常用于开发和调试阶段,用于捕获逻辑错误和不一致之处,而不是作为异常处理的一部分。

在发布版本中,通常会禁用断言以提高性能

什么样的异常会被try-catch捕捉

在 C++ 中,try-catch 块用于捕获和处理异常。在 Qt 中,与标准 C++ 异常处理机制相同,你可以使用 try-catch 块来捕获和处理任何抛出的异常,包括但不限于以下情况:

  1. 标准 C++ 异常:你可以抛出标准 C++ 异常,如 std::exception 及其派生类。这些异常可以通过 try-catch 块捕获和处理。

  2. 自定义异常:你也可以定义自己的异常类,并在需要时抛出并在 try-catch 块中捕获。

  3. Qt 中的异常:虽然 Qt 不鼓励在其库中使用异常,但有些情况下仍会抛出异常,如在一些文件操作或内存分配失败时。这些异常也可以被 try-catch 块捕获。

在使用 try-catch 块时,可以按照以下语法结构来捕获异常:

1
2
3
4
5
6
7
8
9
10
11
12
13
try {
// 可能抛出异常的代码块
throw SomeException(); // 可能抛出异常
} catch (const std::exception& e) {
// 捕获标准 C++ 异常
qDebug() << "Caught standard C++ exception: " << e.what();
} catch (const CustomException& e) {
// 捕获自定义异常
qDebug() << "Caught custom exception: " << e.getMessage();
} catch (...) {
// 捕获所有其他异常
qDebug() << "Caught unknown exception";
}

在上面的示例中,try 块中的代码可能会抛出异常,catch 块用于捕获不同类型的异常。第一个 catch 块捕获标准 C++ 异常,第二个 catch 块捕获自定义异常,最后一个 catch 块捕获所有其他类型的异常。

总的来说,在 Qt 中,try-catch 块可以用来捕获标准 C++ 异常、自定义异常以及某些 Qt 中可能抛出的异常。然而,在 Qt 中,更常见的做法是使用返回错误码和信号槽来处理异常和错误情况,而不是依赖于异常处理机制。

Qt中异常处理

在Qt中,通常不直接抛出标准C++异常来处理错误。相反,Qt倾向于使用错误码和信号槽来处理错误情况。这是因为Qt的信号槽机制提供了一种更灵活、更适合异步事件处理的方式,可以跨线程传递信号,而标准的异常机制在跨线程时会遇到一些问题。

Qt提供了一些用于处理错误和异常情况的机制,例如:

  1. Q_ASSERT:用于在调试模式下检查条件是否为真,如果条件为假,则会输出错误信息并终止程序。在发布版本中,默认会被忽略。可以通过定义QT_NO_DEBUG来禁用这些断言。

  2. Q_CHECK_PTR:类似于Q_ASSERT,用于检查指针是否为nullptr

  3. Q_UNREACHABLE:用于标记代码中不应该被执行到的位置,如果执行到了,会输出错误信息并终止程序。

  4. Q_EMIT:用于发射信号,可以被用来通知错误或异常情况。

  5. QMessageLogger:用于记录消息,可以输出调试、警告、严重和致命错误信息。

虽然Qt本身提供了一些处理错误和异常情况的机制,但在Qt中捕获导致程序崩溃的异常并不是推荐做法。Qt更注重稳定性和健壮性,建议在编写代码时尽量避免出现导致程序崩溃的情况,而是通过良好的设计和错误处理机制来保证程序的稳定性。

enabled 和disabled 的区别

在Qt中,“enabled” 和 “disabled” 分别表示控件(如按钮、文本框等)的状态。当一个控件是 “enabled” 状态时,意味着它是可用的,用户可以与之交互并进行操作。相反,当一个控件是 “disabled” 状态时,它是不可用的,用户无法与之交互或进行操作。

通过设置控件的 “enabled” 属性,你可以控制用户是否可以与该控件进行交互。当一个控件被禁用时,通常会显示为灰色,以示区别于可用的控件。这种状态管理可以帮助你在界面中动态控制用户可以与哪些控件进行交互,从而提供更好的用户体验。

Qt progressBar 设置

setFormat()用于生成当前文本字符串。

  • %p - 被完成百分比所取代
  • %v - 被当前值所取代
  • %m - 被总步数所取代

默认值是 “%p%”。

如果最小值和最大值都设置为0,进度条会显示了一个繁忙指示,而不会显示当前的值。

如何复制组件

在 Qt 中,要复制一个组件(widget),您可以使用 QWidgetQWidget *QWidget::clone() 方法。这个方法会创建并返回一个与原始组件相同的副本。您可以将这个副本添加到您的界面中,或者对其进行其他操作。

以下是一个简单的示例代码,展示如何复制一个 QWidget 组件:

1
2
3
4
5
6
7
8
9
// 假设 widgetToCopy 是您要复制的组件
QWidget *widgetToCopy = new QWidget;
widgetToCopy->setWindowTitle("Original Widget");
widgetToCopy->show();

// 复制组件
QWidget *copiedWidget = widgetToCopy->clone();
copiedWidget->setWindowTitle("Copied Widget");
copiedWidget->show();

在这段代码中,我们首先创建一个名为 widgetToCopyQWidget 组件,并显示它。然后,我们使用 clone() 方法复制这个组件,得到一个副本 copiedWidget,并设置副本的窗口标题为 “Copied Widget”,最后显示副本组件。

请注意,clone() 方法是 Qt 5.15 版本引入的。如果您使用的是早期版本的 Qt,可能需要考虑其他方法来复制组件,比如手动创建一个新的组件并将原始组件的属性和状态复制到新组件中。

QWidget 设置窗口可鼠标穿透

在Qt中,要实现QWidget设置窗口可鼠标穿透,您可以通过设置窗口属性来实现这一功能。具体来说,您可以使用setAttribute(Qt::WA_TransparentForMouseEvents)属性来使窗口忽略鼠标事件,从而实现鼠标穿透效果。

下面是一个简单的示例代码,演示如何设置QWidget使其忽略鼠标事件:

1
2
// 设置窗口忽略鼠标事件
widget->setAttribute(Qt::WA_TransparentForMouseEvents);

在这段代码中,widget是您想要设置为可鼠标穿透的QWidget对象。通过调用setAttribute(Qt::WA_TransparentForMouseEvents),您告诉Qt框架忽略该窗口上的鼠标事件,使其可以穿透到下面的窗口或控件。

请注意,设置窗口为可鼠标穿透后,该窗口上的鼠标事件将不再被触发,而会传递到下面的窗口或控件。这可能会影响用户交互体验,因此请确保在需要的情况下使用此功能。

获取scrollArea内的所有按钮控件

要获取QScrollArea内的所有按钮控件,您需要首先获取QScrollAreaviewport,然后遗留下的是在视口内查找所有按钮控件。以下是一个示例代码演示如何实现这一点:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 假设scrollArea是您的QScrollArea对象

QWidget *viewport = scrollArea->viewport();
if (viewport) {
QList<QPushButton *> buttonList = viewport->findChildren<QPushButton *>();

// 现在buttonList中包含了视口内的所有QPushButton控件
for (QPushButton *button : buttonList) {
// 在这里可以对每个按钮进行操作
// 例如,打印按钮的文本
qDebug() << "Button Text: " << button->text();
}
}

在这段代码中,我们首先获取了QScrollArea的视口部件。然后,我们使用findChildren<QPushButton *>()方法来查找视口内的所有QPushButton控件,并将它们存储在buttonList中。最后,我们遍历buttonList,对每个按钮进行操作,例如打印按钮的文本。

请注意,这段代码假设您正在寻找QPushButton控件。如果您的按钮是其他类型的控件,只需将QPushButton替换为相应的控件类型即可。

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