首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Qt InvokeMethod on TextEdit setPalette

Qt InvokeMethod on TextEdit setPalette
EN

Stack Overflow用户
提问于 2020-09-15 14:36:45
回答 3查看 157关注 0票数 1

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

代码语言:javascript
复制
QString text = "Hello";
QMetaObject::invokeMethod(m_ui.textEdit_ConnectionStatus, "setText", Qt:QueuedConnection, Q_ARG(QString, text));

..。为了改变GUI元素,而不是从主线程。但是,对于setPalette,它似乎没有以相同的方式为textEdit工作。

通过以下方式:

代码语言:javascript
复制
QPalette pal = palette();
pal.setColor(QPalette::Base, Qt:darkGreen);
QMetaObject::invokeMethod(m_ui.textEdit_ConnectionStatus, "setPalette", Qt:QueuedConnection, Q_ARG(const QPalette&, pal));

如何从另一个线程更改这个gui元素的颜色?

Edit1:我忘了提到输出:

QMetaObject::invokeMethod方法QTextEdit:setpalette(const &)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-09-16 05:56:24

OP使用的是QMetaObject::invokeMethod(),它依赖于已注册的插槽(就像在Qt4中通常的那样)。QTextEdit::setText()是这样一个插槽,但QTextEdit::setPalette()不是。

因此,在运行时,不能以字符串的名称找到QTextEdit::setPalette()

利用Qt5,扩展了信号时隙的概念,以支持信号与时隙的连接和编译时检查.

出于好奇,我去看了看医生。并找到接受函子的QMetaObject::invokeMethod()

模板< type type函子,type type bool QMetaObject::invokeMethod(QObject *上下文,函子函数,Qt::ConnectionType = Qt::AutoConnection,FunctorReturnType *ret = nullptr) 这是一个重载的函数。 调用上下文事件循环中的函数。函数可以是函子,也可以是指向成员函数的指针。如果可以调用函数,则返回true。如果没有这样的函数或参数不匹配,则返回false。函数调用的返回值放在ret中。 注意:这个函数是线程安全的. 这一功能是在Qt5.10中引入的。

因此,我想强调注意:这个函数是线程安全的.

所以,我做了一个MCVE来检查这个:

代码语言:javascript
复制
// 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;
}

输出:

请注意,我(仔细地)只访问了一次qTextEdit

  • 在主线程中
  • 或者在传递给QMetaObject::invokeMethod()的lambda中。

默认情况下,Qt小部件不是线程安全的。因此,我必须确保对小部件的访问只发生在GUI线程中(或者必须得到适当的保护)。

qTextEdit的参考被捕获在threadPal的函子中。它用于将qTextEdit的地址作为上下文提供给QMetaObject::invokeMethod()。这对于使QMetaObject::invokeMethod()意识到提供的函子必须在不同的线程(与qTextEdit相关联的GUI线程)中执行是必要的。(与qTextEdit本身相反,当线程运行时,qTextEdit的地址是不可变的。因此,无保护的访问是线程安全的。)

票数 1
EN

Stack Overflow用户

发布于 2020-09-15 16:02:39

根据Qt文档,invokeMethod()调用对象上的成员(信号或槽名)。

因为在第一种情况下,setText()QTextEdit的一个插槽,因此它的工作非常完美。但是,在第二种情况下,setPalette()既不是信号也不是插槽,因此您得到了输出"QMetaObject::invokeMethod No the Method QTextEdit:setpalette(const &)“。

此外,如果没有这样的成员(信号或插槽名)或参数不匹配,则返回false。

请看这里

票数 1
EN

Stack Overflow用户

发布于 2020-09-15 19:52:47

如果使用QT5.10或更高版本,可以对任何可调用的对象(如lambda)调用invokeMethod

代码语言:javascript
复制
QPalette pal = palette();
pal.setColor(QPalette::Base, Qt:darkGreen);

auto setPalette = [this, pal] { m_ui.textEdit_ConnectionStatus->setPalette(pal); };
QMetaObject::invokeMethod(m_ui.textEdit_ConnectionStatus, setPalette, Qt:QueuedConnection);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63904176

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档