0

I'm working with a Qt application that uses an XML file to generate the user interface, via the Qt User Interface Compiler.

I don't have access to the code that holds each widget (I do but the Qt UI Compiler re-generates it each time), so I'm not able to add another method to the class that it generates.

I'm trying to do a setStyleSheet on one of the QLineEdit widgets, but it gives me a QPixmap: It is not safe to use pixmaps outside the GUI thread warning and then eventually seg faults. After resigning myself to not being able to go this route, I decided to test having two copies of each widget, each with the stylesheet values needed. I would then trigger a QLineEdit::hide() and QLineEdit::show() on the widgets as needed, which I thought would work.

It didn't. The program now spits out QCoreApplication::sendPostedEvents: Cannot send posted events for objects in another thread whenever run.

What can I do to fix this? I need to change the stylesheet of the widget dynamically, but seem unable to do so in any manner.

Josh Johnson
  • 563
  • 3
  • 11
  • 29
  • Are you in the main thread (the one where `QApplication` instance was started) when you try to apply the stylesheet? – jpo38 Feb 11 '16 at 20:28
  • 1
    I'm not. It's in a separate thread. It allows me to change the value of the text via `setText("text")`, but I can't set the stylesheet. – Josh Johnson Feb 11 '16 at 20:37
  • No suprise then if it crashs, check Kuba's answer – jpo38 Feb 12 '16 at 10:36

1 Answers1

1

You can't be invoking any QWidget methods from threads other than the main thread. It's fairly easy to indirectly invoke such methods safely from any thread, though. See this answer for details.

For example, suppose you wanted to call setStyleSheet on a widget, from code that runs in some other thread:

template <typename F>
static void postToMainThread(F && fun, QObject * object) {
   QObject signalSource;
   QObject::connect(&signalSource, &QObject::destroyed, object, std::forward(fun));
}

void threadCode(QWidget * widget) {
  postToMainThread([widget]{
    widget->setStyleSheet("color: black");
  }, widget);
}
Community
  • 1
  • 1
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • I've tried to wade through that answer linked, and can't seem to understand how the signal/slot was set up. If I need to set up a signal to send to the main thread to update the stylesheet, how would I got about that? I understand the concept of Signals and Slots, and understand how to connect them. My issue is with making one for a QLineEdit (or any widget). It doesn't seem as though they have any signal that I can use to send to the setStyleSheet slot. – Josh Johnson Feb 12 '16 at 18:38
  • @JoshJohnson You don't need any signals at all, that's taken care of by examples. What you're executing is a functor - a self contained chunk of code - in the main thread. The first section of the answer has everything you need. The `F` template type is meant to be a functor or a function pointer. Pass it a lambda with your code to run, and you're done. – Kuba hasn't forgotten Monica Feb 12 '16 at 20:53