Qt: is there any way to call a sequence of slots with certain time interval? - c++

The way I am working now is to connect a QTimer to the first slot, inside the first slot it will trigger another single-shot QTimer which will trigger the second slot... and so on.
If I update all of the widgets at once, the GUI will stuck for a flash of a second. But it is noticeable. So I want to avoid that.
But this is very difficult to write code. You have to add QTimer everywhere. Are there any better solutions?
EDIT: This is how I update my widget, maybe there is better way?
void UAVInfoView::updateDisplay()
{
if (!visibleRegion().isEmpty()){
info = _dataSrc->getUAVInfo(_id-1);
if (info)
{
//if new package received try to do updating.
if (_pakchk != info->_pakcnt){
//only update the text if there is communication
if (info->_communication != COMMSTATUS::WAIT4CONNECTION && info->_communication != COMMSTATUS::LOST)
{
ui->plainTextEdit->setPlainText(tr("x: %1\ny: %2\nz: %3").arg(info->_pos[0]).arg(info->_pos[1]).arg(info->_pos[2]));
}
//only update the status indicator only if status changed.
if (_status != info->_communication)
{
switch (info->_communication){
case COMMSTATUS::CONNECTED:
ui->groupBox->setStyleSheet("QGroupBox#groupBox {background-color:green;}");
ui->label_2->setText("On Line");
break;
case COMMSTATUS::LOST:
ui->groupBox->setStyleSheet("QGroupBox#groupBox {background-color:red;}");
ui->label_2->setText("Lost");
break;
case COMMSTATUS::WAIT4CONNECTION:
ui->groupBox->setStyleSheet("QGroupBox#groupBox {background-color:grey;}");
ui->label_2->setText("Off Line");
}
}
}
//update the status and package counter to serve the state machine.
_status = info->_communication;
_pakchk = info->_pakcnt;
}
}
}
As you can see, it is just a bunch of default =, ! if else things...

You can call them in a slot connected to a timer with a certain interval. Your slot that is connected to the timer could be like :
void myClass::onTriggered()
{
switch(turn){
case 0:
slot1();
break;
case 1:
slot2();
break;
...
}
turn++;
if(turn>=numberOfSlots)
turn = 0;
}
This way each time one slot is called and they are called sequentially.

I'm not quite sure what you try to achieve, but if you want to trigger the execution of a specific set of functions with a timer, you probably have to introduce some controlling instance with a singe QTimer that you can use as often as you like.
Now that you said you don't want to update all your GUI widgets all the time, and I guess you are using QWidgets, you could also use the setUpdatesEnabled(bool) method to disable all effects of update() or repaint() calls.
If this doesn't help you, maybe you can explain you problem a bit more detailed?

Although I believe the problem is somewhere else, I'll give you one possible solution. You could use a state machine. Just have one slot that is triggered by your timer in which you call some other functions based on the current state.
...
connect(&timer, SIGNAL(timeout()), this, SLOT(myStateSlot()));
timer.start(1000);
...
void MyClass::myStateSlot()
{
switch(state)
{
case State_Start:
operation1();
// you can change the state here.. or somewhere else.. up to your design
break;
case State_Two:
operation2();
break;
case State_End:
timer.stop();
break;
}
}

Your problems likely stem from the relative slowness of the QPlainTextEdit. Use a QLabel instead. Otherwise, the code looks fine. Make sure that if there are multiple consequent calls to updateDisplay, they should all happen without the control returning to the event loop between the calls.
The below is wrong, since each processEvents forces a repaint of the widgets.
w.updateDisplay();
QCoreApplication::processEvents();
w.updateDisplay();
QCoreApplication::processEvents();
You might be invoking processEvents() without realizing it. It is effectively invoked every time you return from QObject::event() and the event queue is empty at the time. Also note that QObject::event() is the caller of queued slot calls. Thus, if you have a queued connection to a slot, the control returns to the event loop right after the slot returns.

If the update method is complex, you should try QtConcurrent::map() to run the update in another thread. Then you need no delay, because you'll get notified from map() when the updates are finished.

Related

QLabel not updating from slot call

My QLabel is not updating from slot. I run sender class in separate thread using QObject::moveToThread:
QThread* serviceThread = new QThread;
service = new ExportService();
connect(service,SIGNAL(stateChanged(Service::ServiceState)),
this,SLOT(statusChanged(Service::ServiceState)));
service->moveToThread(serviceThread);
serviceThread->start();
Service object send states by emiting signal with ServiceState enum value, this signal is captured by QDialog slot:
void Dialog::statusChanged(Service::ServiceState s)
{
switch (s) {
case Service::IDLE:
qDebug() << "Idle";
ui->label->setText("Service send response succesfully.");
break;
case Service::REQUESTING:
qDebug() << "Requesting";
ui->label->setText("Requesting response from service...");
break;
case Service::ERROR:
qDebug() << "Error";
ui->label->setText("Error. Cannot get response from service.");
break;
default:
break;
}
}
After operation on the object which emits a signal twice, the first time with value of Service::REQUESTING and second time with value of Service::IDLE my QLabel change text only to "Service send response succesfully.". In the console I can see that qDebug() << "Requesting"; works so the state changed successfully.
After comment out ui->label->setText("Service send response succesfully."); label has changed to requesting state but after the whole operation was done ie i see "Requesting" in console then "Idle" and after that QLabel has changed.
What should I do if I want to see QLabel changing in realtime?
First, try adding update() after setText(), chances are setText() doesn't automatically schedule a repaint() for the QLabel, if it works then problem solved.
However, for update() function:
http://doc.qt.io/qt-4.8/qwidget.html#update
void QWidget::update()
This function does not cause an immediate repaint; instead it
schedules a paint event for processing when Qt returns to the main
event loop. This permits Qt to optimize for more speed and less
flicker than a call to repaint() does.
> Calling update() several times normally results in just one
paintEvent() call.
which basically says, if you call them too frequently and some of them will be optimized away.
If this is not the desired behaviour, try adding a forced repaint() after setText(), or using a timer to schedule periodical forced repaints.
http://doc.qt.io/qt-4.8/qwidget.html#repaint
UPDATE
As is mentioned in the comment, forcing repaint() isn't good solution.
This answer is intended to provide an analysis of the cause of the code's behaviour and the "forced repaint()" suggestion is more of a way to verify this analysis than a solution to the problem.
However, without further information on the purpose of the program, it's very difficult to provide further suggestions.
The status change from requesting to idle happens quickly. The text "Requesting response from service..." is not on the label long enough for the eye to see it.
The fact that "Requesting ..." is in the debug output is proof of this, but if you want more proof there are other things you could do:
use a counter that counts each time the statusChanged() function is called and display this either in the same label as the status text (in addition to the status text) or a different label.
add a high accuracy timer output to the debug outputs - see how close together the status changes are.
use a couple of check boxes, one for idle status and one for requesting status. Change their state when the appropriate status is received. That is whne the first Idle is received set the check box to checked. When the next idle is received toggle it to unchecked.
I would just accept that the debug outputs are telling the truth and move on.

Qt - GUI freezing

I wrote in C++ a solver for the 8-puzzle game, and now I'm trying to use Qt to give it a GUI.
Basically I have an underlying object of type "Board" which represents the board of the puzzle, and I have organized the GUI as a grid of QPushButton. Then I have a method updateUI which associates to every button the correct text, based on the Board. Something like
for(int i=0; i<Board::MATRIX_DIM * Board::MATRIX_DIM; i++)
{
m_buttons[i]->setText(m_values[i]);
}
In another method (solveGUI) I have
void MainWindow::solveGUI()
{
m_game->solve();
int solutionDepth = m_game->getSolutionDepth();
Move *solutionMoves = m_game->getSolutionMoves();
for(int i=0; i<solutionDepth; i++)
{
Move m = solutionMoves[i];
m_board.performMove(m); /* perform the move on the Board object */
updateUI(); /* should update the GUI so that it represents the Board */
Sleep(1000);
}
}
where the first line (m_game->solve) takes some time. Then I obtain a list of the moves performed, in solutionMoves, and what I would like to do is showing this moves on the board, with some delay between a move and the next one. This method is called by my main, which looks like this:
QApplication app(argc, argv);
MainWindow w;
w.show();
w.solveGUI();
return app.exec();
The result is that the GUI hangs and, after some time, it displays only the solution, completely skipping the moves.
What am I missing? Thank you!
P.S. I don't think I need a different Thread for the solver because I want the solver to run before the solution is displayed. Is it right?
It's app.exec() that actually runs the main loop which handles all events, including displaying GUI. If you want to call solve() before that, it's OK, but if you want to actually display and update GUI before exec(), it's wrong. I'm not sure if it's totally impossible, but it's definitely not the right way to do it.
There are two ways around it. The more canonical way is to redesign a program using a QTimer. Then everything will be smooth and responsive. But that can be tedious sometimes. In your case it should be quite easy, though. Just save the results somewhere, and call a slot using a QTimer object every 1000 seconds - it will have the same effect as your Sleep(), but will keep everything responsive.
The other solution is to call your solveGUI() method after exec() starts its job. It can be done, for example, using QTimer::singleShot():
QTimer::singleShot(0, &w, SLOT(showGUI()));
return app.exec();
Then, before each Sleep(), you should call QApplication::processEvents(), which basically allows you to temporary yield control, processing all pending events, including GUI updates. This approach is somewhat easier, but it's inferior since the GUI still freezes at each Sleep(). For example, if the user wants to exit the application, or if the window is needed to be repainted, it will cause uncomfortable GUI lags.
You're stalling the main thread (which also does the event processing) and rendering it uncapable of responding to keyboard/mouse/window messages.
You should use an asynchronous timer operation instead of the sleep function: use a QTimer to delay showing the next solution and avoid messages being left unanswered for too long.
There is a nice article of methods to keep the GUI responsive during processing loops. if it's not a complicated case I think, just insert QCoreApplication::processEvents(); inside the long processing loops.
try the following:
void MainWindow::Wait(int interval ) {
QTime timer = new QTime;
timer.restart();
while(timer.elapsed() < interval) {
QApplication::processEvents();
}
}
...
for(...) {
//wait 1 second (1000 milliseconds) between each loop run at first
Wait(1000);
...
}
...
not tested yet - but should work (maybe there is some cpu load)!

Qt/C++: Checkable button and infinite loop

I'm coding a Qt Gui and I'm trying to implement a new feature, I now the precise result I want to arrive at but not how to code it.
I'm trying to add a checkable button that when checked would run a function that would only stop when the button is unchecked, but every second a PaintArea I have on the window would be updated (letting me see how the multiple executions of my function are changing my data). It seem that I'll need to use some QThread objects, but just the part dealing with the button is already counter intuitive to me, I've been trying to play with the autoRepeatDelay and autoRepeatInterval without getting my hand on what they do and how they could be useful to me.
I guess that what I'm trying to code is not really original, would have an idea of the steps to implement it, or an example of a code?
Edit:
According to the first answers (thank you for them by the way) my question may not be clear. Putting on the side the thread thing, I'd like to implement an infinite loop that only starts when a pressbutton goes to pressed position (it's a checkable button) and stops only when leaving it. The first version I tried to do (with a while(button->isChecked() loop) would completely freeze as the application would be running the loop, the gui would freeze and the button couldn't be turned off (hence the idea of running it in a separate thread). Voila! I hope it's a clearer formulation. Thank you in advance.
Here's a simple skeleton of something that might work. Without knowing your exact requirements, it may or may not be right for your problem. Hopefully it will give you a few hints that do actually help.
void Ui::buttonPressedSlot(bool checked){
if (checked){
Processor *processor = new Processor;
connect(this, SIGNAL(abortCalculations()), processor, SLOT(abort()), Qt::QueuedConnection);
connect(processor, SIGNAL(updateNeeded()), this, SLOT(updateGui()), Qt::QueuedConnection);
QThreadPool::globalInstance()->start(processor);
} else {
emit abortCalculations(); // this is a signal in your UI class
}
}
You can then use the following for your calculations.
class Processor : public QObject, public QRunnable{ // QObject must always be first in multiple inheritance
Q_OBJECT
public:
~Processor();
void run();
public slots:
void abort();
void doCalculations();
signals:
void updateNeeded(); // connect this to the GUI to tell it to refresh
private:
QScopedPointer<QEventLoop> loop;
};
Processor::~Processor(){
abort();
}
void Processor::run() {
loop.reset(new QEventLoop);
QTimer timer;
connect(&timer, SIGNAL(timeout()), this, SLOT(doCalculations()));
timer.setInterval(1000);
timer.start();
loop->exec();
}
void Processor::abort(){
if (!loop.isNull()){
loop->quit();
}
}
void Processor::doCalculations(){
// do whatever needs to be done
emit updateNeeded();
}
I don't know if I really understand what you want to do, but I will try to answer.
First, you want a Button that send a start & stop info to control a thread. You can use a checkbox to begin. This check box send a signal when its state changes. Connect this signal to a slot that perform start thread and stop according to the boolean sent.
Second, in you thread you need to launch the events loop. After, set a timer that call you repaint after every timeout.
Hope it helped.
PS: take care of execution context with you thread and Qt's objects.

How to make sure that readyRead() signals from QTcpSocket can't be missed?

When using QTcpSocket to receive data, the signal to use is readyRead(), which signals that new data is available.
However, when you are in the corresponding slot implementation to read the data, no additional readyRead() will be emitted.
This may make sense, as you are already in the function, where you are reading all the data that is available.
Problem description
However assume the following implementation of this slot:
void readSocketData()
{
datacounter += socket->readAll().length();
qDebug() << datacounter;
}
What if some data arrives after calling readAll() but before leaving the slot?
What if this was the last data packet sent by the other application (or at least the last one for some time)?
No additional signal will be emitted, so you have to make sure to read all the data yourself.
One way to minimize the problem (but not avoid it totally)
Of course we can modify the slot like this:
void readSocketData()
{
while(socket->bytesAvailable())
datacounter += socket->readAll().length();
qDebug() << datacounter;
}
However, we haven't solved the problem. It is still possible that data arrives just after the socket->bytesAvailable()-check (and even placing the/another check at the absolute end of the function doesn't solve this).
Making sure to be able to reproduce the problem
As this problem of course happens very rarely, I stick to the first implementation of the slot, and I'll even add a an artificial timeout, to be sure that the problem occurs:
void readSocketData()
{
datacounter += socket->readAll().length();
qDebug() << datacounter;
// wait, to make sure that some data arrived
QEventLoop loop;
QTimer::singleShot(1000, &loop, SLOT(quit()));
loop.exec();
}
I then let another application send 100,000 bytes of data.
This is what happens:
new connection!
32768 (or 16K or 48K)
The first part of the message is read, but the end isn't read anymore, as readyRead() won't be called again.
My question is: what is the best way to be sure, this problem never occurs?
Possible solution
One solution I came up with is calling the same slot again at the end again, and to check at the beginning of the slot, if there is any more data to read:
void readSocketData(bool selfCall) // default parameter selfCall=false in .h
{
if (selfCall && !socket->bytesAvailable())
return;
datacounter += socket->readAll().length();
qDebug() << datacounter;
QEventLoop loop;
QTimer::singleShot(1000, &loop, SLOT(quit()));
loop.exec();
QTimer::singleShot(0, this, SLOT(readSocketDataSelfCall()));
}
void readSocketDataSelfCall()
{
readSocketData(true);
}
As I don't call the slot directly, but use QTimer::singleShot(), I assume that the QTcpSocket can't know that I'm calling the slot again, so the problem that readyRead() isn't emitted can't happen anymore.
The reason why I have included the parameter bool selfCall is that the slot which is called by the QTcpSocket isn't allowed to exit sooner, else the same problem can occur again, that data arrives exactly at the wrong moment and readyRead() isn't emitted.
Is this really the best solution to solve my problem?
Is the existence of this problem a design error in Qt or am I missing something?
Short answer
The documentation of QIODevice::readyRead() states:
readyRead() is not emitted recursively; if you reenter the event loop or call waitForReadyRead() inside a slot connected to the readyRead() signal, the signal will not be reemitted.
Thus, make sure that you
don't instantiate a QEventLoop inside your slot,
don't call QApplication::processEvents() inside your slot,
don't call QIODevice::waitForReadyRead() inside your slot,
don't use the same QTcpSocket instance within different threads.
Now you should always receive all data sent by the other side.
Background
The readyRead() signal is emitted by QAbstractSocketPrivate::emitReadyRead() as follows:
// Only emit readyRead() when not recursing.
if (!emittedReadyRead && channel == currentReadChannel) {
QScopedValueRollback<bool> r(emittedReadyRead);
emittedReadyRead = true;
emit q->readyRead();
}
The emittedReadyRead variable is rolled back to false as soon as the if block goes out of scope (done by the QScopedValueRollback). So the only chance to miss a readyRead() signal is when the control flow reaches the if condition again before the processing of the last readyRead() signal has finished (in other words, when there would be a recursion).
And a recursion should only be possible in the situations listed above.
I think scenario mentioned in this topic has two major cases which works differently, but in general QT doesn't have this problem at all and I will try to explain below why.
First case: Single threaded application.
Qt uses select() system call to poll open file descriptor for any change happened or operations available. Simple saying on every loop Qt checks if any of opened file descriptors have data available to read/closed etc. So on single threaded application flow looks like that (code part simplified)
int mainLoop(...) {
select(...);
foreach( descriptor which has new data available ) {
find appropriate handler
emit readyRead;
}
}
void slotReadyRead() {
some code;
}
So what will happend if new data arrived while program still inside slotReadyRead.. honestly nothing special. OS will buffer data, and as soon as control will return to next execute of select() OS will notify software that there are data available for particular file handle. It works in absolutely the same way for TCP sockets/files etc.
I can imaging situations where (in case of really long delays in slotReadyRead and a lot of data coming) you can experience an overrun within OS FIFO buffers (for example for serial ports) but that has more to do with a bad software design rather then QT or OS problems.
You should look on slots like readyRead like on a interrupt handlers and keep their logic only within fetch functionality which fills your internals buffers while processing should be done in separate threads or while application on idle etc.. Reason is that any such application in general is a mass service system and if it spends more time on serving one request then a time interval between two requests it's queue will overrun anyway.
Second scenario: multithreaded application
Actually this scenario is not that much differ from 1) expect that you should design right what happens in each of your threads. If you keep main loop with light wighted 'pseudo interrupt handlers' you will be absolutely fine and keep processing logic in other threads, but this logic should work with your own prefetch buffers rather then with QIODevice.
The problem is quite interesting.
In my program the usage of QTcpSocket is very intensive. So I've written the whole library, that breaks outgoing data into packages with a header, data identifier, package index number and maximum size, and when the next piece of data comes, I know exactly where it belongs to. Even if I miss something, when the next readyRead comes, the receiver reads all and compose received data correctly. If the communication between your programs is not so intense, you could do the same, but with timer (which is not very fast, but solves the problem.)
About your solution. I don't think it's better then this:
void readSocketData()
{
while(socket->bytesAvailable())
{
datacounter += socket->readAll().length();
qDebug() << datacounter;
QEventLoop loop;
QTimer::singleShot(1000, &loop, SLOT(quit()));
loop.exec();
}
}
The problem of both methods is the code right after leaving the slot, but before returning from emitting the signal.
Also you could connect with Qt::QueuedConnection.
Here are some examples of ways to get the whole file, but using some other parts of the QNetwork API:
http://qt-project.org/doc/qt-4.8/network-downloadmanager.html
http://qt-project.org/doc/qt-4.8/network-download.html
These examples show a stronger way to handle the TCP data, and when buffers are full, and better error handling with a higher level api.
If you still want to use the lower level api, here is a post with a great way to handle the buffers:
Inside your readSocketData() do something like this:
if (bytesAvailable() < 256)
return;
QByteArray data = read(256);
http://www.qtcentre.org/threads/11494-QTcpSocket-readyRead-and-buffer-size
EDIT: Additional examples of how to interact with QTCPSockets:
http://qt-project.org/doc/qt-4.8/network-fortuneserver.html
http://qt-project.org/doc/qt-4.8/network-fortuneclient.html
http://qt-project.org/doc/qt-4.8/network-blockingfortuneclient.html
Hope that helps.
If a QProgressDialog shall be shown while receiving data from a socket it only works if any QApplication::processEvents() are sent (e.g. by the QProgessDialog::setValue(int) methode). This of course leads to the loss of readyRead signals as mentioned above.
So my workaround was a while loop including the processEvents command such as:
void slot_readSocketData() {
while (m_pSocket->bytesAvailable()) {
m_sReceived.append(m_pSocket->readAll());
m_pProgessDialog->setValue(++m_iCnt);
}//while
}//slot_readSocketData
If the slot is called once any additional readyRead signals can be ignored because the bytesAvailable() always returns the actual number after the processEvents call. Only on pausing of the stream the while loop ends. But then the next readReady is not missed and starts it again.
I had the same problem right away with the readyRead slot. I disagree with the accepted answer; it doesn't solve the problem. Using bytesAvailable as Amartel described was the only reliable solution I found. Qt::QueuedConnection had no effect. In the following example, I'm deserializing a custom type, so it's easy to predict a minimum byte size. It never misses data.
void MyFunExample::readyRead()
{
bool done = false;
while (!done)
{
in_.startTransaction();
DataLinkListStruct st;
in_ >> st;
if (!in_.commitTransaction())
qDebug() << "Failed to commit transaction.";
switch (st.type)
{
case DataLinkXmitType::Matrix:
for ( int i=0;i<st.numLists;++i)
{
for ( auto it=st.data[i].begin();it!=st.data[i].end();++it )
{
qDebug() << (*it).toString();
}
}
break;
case DataLinkXmitType::SingleValue:
qDebug() << st.value.toString();
break;
case DataLinkXmitType::Map:
for (auto it=st.mapData.begin();it!=st.mapData.end();++it)
{
qDebug() << it.key() << " == " << it.value().toString();
}
break;
}
if ( client_->QIODevice::bytesAvailable() < sizeof(DataLinkListStruct) )
done = true;
}
}
i got the same problem, rather use signal readyRead() and socket.readall, i' m trying the following, just after connect without be sure :
QByteArray RBuff;
if(m_socket->waitForConnected(3000))
{
while (m_socket->ConnectedState == QAbstractSocket::ConnectedState) {
RBuff = m_socket->read(2048);
SocketRead.append(RBuff);
if (!SocketRead.isEmpty() && SocketRead.length() == 2048)
{
readData(SocketRead);
SocketRead.remove(0,2048);
}
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
//m_socket->close();*/
}
else
{

How do I progressively load a widget in QT?

I have a custom widget which displays many items in rows:
void update(){ //this is a SLOT which is connected to a button click
QVBoxLayout *layout = this->layout();
if (layout == NULL){
layout = new QVBoxLayout;
this->setLayout(layout);
} else {
QLayout_clear(layout); //this is a function that I wrote that deletes all of the items from a layout
}
ArrayList *results = generateData(); //this generates the data that I load from
for (int i = 0; i < results->count; i++){
layout->addWidget(new subWidget(results->array[i]));
}
}
The problem is that there are about 900 items and a profile reveals that simply adding the child object to the layout takes 50% of the time (constructing takes the other 50%). Overall it takes about 3 seconds to load all of the items.
When I click on the button to load more data, the entire UI freezes for the 3 seconds and then all of the items appear together when everything is done. Is there a way to progressively load more items as they are being created?
The first trick is, as Pavel Zdenek said, to process only some of the results. You want to process as many together so that the overhead (of what we're going to do in the next step) is low, but you don't want to do anything that would make the system seem unresponsive. Based on extensive research, Jakob Nielsen says that "0.1 seconds is about the limit for having the user feel that the system is reacting instantaneously", so as a rough estimate you should cut your work into roughly 0.05 second chunks (leaving another 0.05 seconds for the system to actually react to the user's interactions).
The second trick is to use a QTimer with a timeout of 0. As the QTimer documentation says:
As a special case, a QTimer with a timeout of 0 will time out as soon
as all the events in the window system's event queue have been
processed. This can be used to do heavy work while providing a snappy
user interface.
So that means that a timer with a timeout of 0 will be executed next, unless there is something else in the event queue (for instance, a mouse click). Here's the code:
void update() {
i = 0; // warning, this is causes a bug, see below
updateChunk();
}
void updateChunk() {
const int CHUNK_THRESHOLD = /* the number of things you can do before the user notices that you're doing something */;
for (; i < results->count() && i < CHUNK_THRESHOLD; i++) {
// add widget
}
// If there's more work to do, put it in the event queue.
if (i < results->count()) {
// This isn't true recursion, because this method will return before
// it is called again.
QTimer::singleShot(0, this, SLOT(updateChunk()));
}
}
Finally, test this a little bit because there's a gotcha: now the user can interact with the system in the "middle" of your loop. For instance, the user can click the update button while you're still processing results (which in the above example means that you would reset the index to 0 and reprocess the first elements of the array). So a more robust solution would be to use a list instead of an array and pop each element off the front of the list as you process it. Then whatever adds results would just append to the list.
#Adri is generally right, the twist is that the "another thread" must be the UI thread again. The point is to allow UI thread's event loop to keep spinning. The fast and dirty way is to put QCoreApplication::processEvents() in your for() cycle. Dirty because, as the doc says, it should be called "ocassionally". It might have some overhead even if there are no UI events, and you are messing Qt's performance optimization as to when and how often spin the loop. Slightly less dirty would be to call it only ocassionally, after chunks of result.
Cleaner and proper way is to create a private slot, which pops one result element (or chunk, to speed up), adds to the layout and increments index. Then it will recall itself until end of results. The gotcha is to define connect() with forced connection type Qt::QueuedConnection, so it will get deferred after already queued UI events (if any).
And because you run in only one thread, you don't need any locking over results.
Adding example per OP's request:
While #TomPanning solution is correct, it kind of hides the real solution behind QTimer which you don't need - you don't need any timing, you just need a specific non-timer behavior upon specific parameter value. This solution does the same thing, minus the QTimer layer. On the other hand, #TomPanning has a very good point about the plain ArrayList not being very good data storage, when interaction can happen in between.
something.h
signals: void subWidgetAdded();
private slots: void addNextWidget();
ArrayList* m_results;
int m_indexPriv;
something.cpp
connect(this,SIGNAL(subWidgetAdded()),
this,SLOT(addNextWidget(),
Qt::QueuedConnection);
void addWidget() {
// additional chunking logic here as you need
layout->addWidget(new subWidget(results->array[m_indexPriv++]));
if( m_indexPriv < results->count() ) {
emit subWidgetAdded(); // NOT a recursion :-)
}
}
void update() {
// ...
m_results = generateData();
m_indexPriv = 0;
addNextWidget(); // slots are normal instance methods, call for the first time
}