Forcing the Qt Gui to Update Before Entering a Separate Function

Forcing the Qt GUI to update before entering a separate function

You shuld be able to process the event queue before entering your code if you;

#include <QApplication>

and, when you want to refresh your GUI, call;

qApp->processEvents();

Note that it may be a good idea to let your long running process call that function now and then, to make your GUI feel more responsive.

refresh/update GUI during slot running

This is what I ended up doing back then. "qApp->processEvents();" was the key. Repaint() is not enough.

void Widget::SetStatus(QString status)
{
ui->Status->setText(status);
ui->Status->repaint();
qApp->processEvents();
}

Forcing the Qt GUI to update

The cause of the crash can be a variety of reasons but if I had to take a guess I'd say you're probably calling methods of a GUI object (label, textbox, your game board, etc.) from the AI thread.

The way threads communicate with one another in Qt is through a mechanism called signals and slots: the AI thread should expose a set of signals, i.e. 'beginThink', 'endThink', and the UI thread should register to those signals (with slots) and react accordingly. This is documented pretty throughly in the docs.

How to force Qt to update GUI from not main thread

If I understand your code correctly, you're trying to log from a background thread and are using a direct connection to pass the signal to the GUI thread? That's not going to work, you have to send the signal via the default connection so Qt can figure out that it's a cross-thread signal and pass it across threads accordingly (ie, via the message loop on the foreground thread).

In Qt, any GUI interaction has to happen in the Main/foreground thread otherwise bad things happen as you discovered. You can certainly send a signal from a background thread to trigger a GUI update - I do this all the time - but you need to ensure that you're using the correct connection for it. The direct connection results in a direct function call and is not going to work for you in this case.

In your code, the problem is the call to connect() - you explicitly specify the connection mode for the signal to slot connection when you should just use the default setting. If you set the connection explicitly to Qt::DirectConnection, the underlying code will execute a direct call to the specified slot, which means that you end up calling the slot in the thread context of the signal. You don't want that because the signal is triggered in a background thread.

PyQT force update textEdit before calling other function

The repaint is called in event loop so sleep the whole thread does not change anything.

You can call repaint manually by:

self.startDialogTextEdit.repaint()

or call static method:

QCoreApplication.processEvents()

which also call repaint internally

Qt - updating main window with second thread

but the problem is that, i cannot reach the
ana->ui->horizontalLayout_4->addWidget(label);

Put your UI modifications in a slot in your main window, and connect a thread signal to that slot, chances are it will work. I think only the main thread has access to the UI in Qt. Thus if you want GUI functionality, it must be there, and can be only signaled from other threads.

OK, here is a simple example. BTW, your scenario doesn't really require to extend QThread - so you are better off not doing it, unless you really have to. That is why in this example I will use a normal QThread with a QObject based worker instead, but the concept is the same if you subclass QThread:

The main UI:

class MainUI : public QWidget
{
Q_OBJECT

public:
explicit MainUI(QWidget *parent = 0): QWidget(parent) {
layout = new QHBoxLayout(this);
setLayout(layout);
QThread *thread = new QThread(this);
GUIUpdater *updater = new GUIUpdater();
updater->moveToThread(thread);
connect(updater, SIGNAL(requestNewLabel(QString)), this, SLOT(createLabel(QString)));
connect(thread, SIGNAL(destroyed()), updater, SLOT(deleteLater()));

updater->newLabel("h:/test.png");
}

public slots:
void createLabel(const QString &imgSource) {
QPixmap i1(imgSource);
QLabel *label = new QLabel(this);
label->setPixmap(i1);
layout->addWidget(label);
}

private:
QHBoxLayout *layout;
};

... and the worker object:

class GUIUpdater : public QObject {
Q_OBJECT

public:
explicit GUIUpdater(QObject *parent = 0) : QObject(parent) {}
void newLabel(const QString &image) { emit requestNewLabel(image); }

signals:
void requestNewLabel(const QString &);
};

The worker object is created and moved to another thread, then connected to the slot that creates the labels, then its newLabel method is invoked, which is just a wrapper to emit the requestNewLabel signal and pass the path to the image. The signal is then passed from the worker object/thread to the main UI slot along with the image path parameter and a new label is added to the layout.

Since the worker object is created without parent in order to be able to move it to another thread, we also connect the thread destroyed signal to the worker deleteLater() slot.

How does one update a field from outside the __init__() function with pyqt5

It turned out that I needed to add repaint(). I also switched to a QLineEdit as this seemed to work better for me. So inside the while loop I now have:

self.ui.lineEdit_temp.setText(str(temp))
self.ui.lineEdit_temp.repaint()

This now outputs live updates to the GUI while reading the data stream.



Related Topics



Leave a reply



Submit