I have an existing multithreaded application I'm trying to slap a very simple QT GUI onto the front end of.
In particular, I've tried to implement a very simple log using a QPlainTextEdit object. Whenever one of these OS threads kicks off a certain action, I'm putting some diagnostic info in the widget with a call to its appendPlainText()
method.
Of course my first crack at this had synchronization issues, so I created a class wrapping the QPlainEdit with a mutex to synchronize things. Essentially this:
class synced_output {
public:
std::mutex mutex;
QPlainTextEdit & text;
synced_output (QPlainTextEdit * text_output) : text(*text_output) {}
void put_line (const std::string & line) {
std::lock_guard<std::mutex> lock(mutex);
text.appendPlainText(line.c_str());
}
private:
synced_output operator= (synced_output &){}
};
That seems to have fixed the race condition nicely. However, the contents of the PlainTextEdit widget do not visibly update until I go interact with the window in some way (merely clicking it suffices). If it adds enough text, I can see the scrollbar come up and move around, but no text until I click.
Based on some advice I saw online, I tried putting a text.repaint()
in there, but that just causes a crash complaining "Cannot send events to objects owned by a different thread". Which makes sense I suppose, but I still need to do so. So how can I get this to display properly after a change? Is there some other better idiom for handling QT calls to change widget contents from multiple OS threads?