gpt4 book ai didi

c++ - TextEdit setPalette 上的 Qt InvokeMethod

转载 作者:行者123 更新时间:2023-12-02 09:51:56 25 4
gpt4 key购买 nike

与 C# 类似,我使用了一个工作片段,例如:

QString text = "Hello";
QMetaObject::invokeMethod(m_ui.textEdit_ConnectionStatus, "setText", Qt:QueuedConnection, Q_ARG(QString, text));
...为了更改不是来自主线程的 GUI 元素。但是,它似乎与 textEdit 的 setPalette 的工作方式不同。
和:
QPalette pal = palette();
pal.setColor(QPalette::Base, Qt:darkGreen);
QMetaObject::invokeMethod(m_ui.textEdit_ConnectionStatus, "setPalette", Qt:QueuedConnection, Q_ARG(const QPalette&, pal));
如何从另一个线程更改此 gui 元素的颜色?
编辑1:
我忘了提到输出吐出:
“QMetaObject::invokeMethod 没有这样的方法 QTextEdit:setpalette(const QPalette&)”

最佳答案

OP 使用了 QMetaObject::invokeMethod()它依赖于已注册的插槽(在 Qt4 中很常见)。 QTextEdit::setText()是这样一个插槽,但QTextEdit::setPalette()不是。
因此,QTextEdit::setPalette()在运行时无法通过以字符串形式给出的名称找到。
在 Qt5 中,信号槽的概念得到了扩展,以支持通过编译时检查来连接信号和槽。
出于好奇,我查看了文档。并找到 QMetaObject::invokeMethod()它接受一个仿函数:

template <typename Functor, typename FunctorReturnType> bool QMetaObject::invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr)

This is an overloaded function.

Invokes the function in the event loop of context. function can be a functor or a pointer to a member function. Returns true if the function could be invoked. Returns false if there is no such function or the parameters did not match. The return value of the function call is placed in ret.

Note: This function is thread-safe.

This function was introduced in Qt 5.10.


因此,我想强调 注:这个函数是线程安全的。
所以,我做了一个 MCVE 来检查一下:
// standard C++ header:
#include <chrono>
#include <thread>

// Qt header:
#include <QtWidgets>

// main application
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// setup GUI
QTextEdit qTextEdit(QString(
"<p>Hello world.</p>"
"<p>Hello Qt.</p>"
"<p>Hello Stack Overflow.</p>"));
qTextEdit.show();
// a separate thread to manipulate qTextEdit
std::thread threadPal([&qTextEdit]() {
using namespace std::chrono_literals;
const QColor qColors[] = { Qt::red, Qt::green, Qt::blue, Qt::white };
QColor qColor;
for (const QColor &qColor_ : qColors) {
std::this_thread::sleep_for(1s);
qColor = qColor_;
QMetaObject::invokeMethod(&qTextEdit, [&qTextEdit, qColor]() {
QPalette qPal = qTextEdit.palette();
qPal.setColor(QPalette::Base, qColor);
qTextEdit.setPalette(qPal);
});
}
});
// runtime loop
const int ret = app.exec();
// done
threadPal.join();
return ret;
}
输出:
snapshot of testQWidgetSetPaletteThreadSafe (animated)
请注意,我(小心地)完成了对 qTextEdit 的所有访问。只
  • 在主线程
  • 或在传递给 QMetaObject::invokeMethod() 的 lambda 内.

  • Qt 小部件默认不是线程安全的。因此,我必须确保对小部件的访问仅发生在 GUI 线程中(或者必须得到适当的保护)。 qTextEdit的引用在 threadPal 的仿函数中被捕获.用于提供 qTextEdit的地址至 QMetaObject::invokeMethod()作为上下文。这是制作 QMetaObject::invokeMethod() 所必需的。注意所提供的仿函数必须在不同的线程中执行( qTextEdit 关联的 GUI 线程)。 (与 qTextEdit 本身相反, qTextEdit 的地址在线程运行时是不可变的。因此,不 protected 访问是线程安全的。)

    关于c++ - TextEdit setPalette 上的 Qt InvokeMethod,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63904176/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com