Changing QLineEdit TextBox's inside of loop dynamically - c++

I'm building some code where I'm running a while loop and, within the loop, am trying to change the contents of a couple of textboxes with QLineEdit's setText(). However, merely calling setText within the loop does not work; the textboxes only change their actual value once the code has run through, instead of at each iteration.
I have little experience with C++ or Qt, but the project I'm working on must use them. Any help?
EDIT: I'm guessing this must be something simple that I simply am having troubles because of my lack of familiarity/knowledge, but if more information is needed I'll gladly provide it!

The problem is that QT needs control to return to the UI thread's event loop in order to update the QLineEdit's visual appearance. The quick and dirty way to run the event loop is to add QCoreApplication::processEvents() after each call to setText(). The proper way to fix it is to move the blocking process that sets the value of the text box into another thread, expose an updateText(QString text) signal, connect it to the TextBox's setText(const QString & text) slot and emit that signal whenever you want the text to be updated.
Please see my answer to a similar question for more detail: unexplained delay after QProgressBar finish loading
You might also want to check out some of the documentation on QThreads and the Qt signal slot system: http://harmattan-dev.nokia.com/docs/library/html/qt4/threads-qobject.html

In my case, calling only repaint() or processEvents() won't do the job.
Within your function loop, call both QCoreApplication::processEvents(); and repaint();:
for (i;...)
{
//do your calculations
//...
QCoreApplication::processEvents();
repaint();
}
Calling ui->mywidget->update() didn't make any different as well.
(Tested for Qt4.8.3 on Kubuntu 12.10 and Qt5.0.1 on Windows XP)

Related

What is the correct way to display widgets without calling QApplication::exec()?

For test purposes I'd like to create and display a widget. For now I only need the widget to render correctly but in the future I may want to extend this so I simulate various events to see how the widget behaves.
From various sources it would appear that the following should work:
QApplication app;
QPushButton button("Hello");
button.show();
// Might also be necessary:
QApplication::processEvents();
But for me the widget does not render correctly. A window is created to display the widget, however it is entirely black.
I can get the widget to render correctly by adding the following lines:
std::this_thread::sleep_for(std::chrono::milliseconds(10));
QApplication::processEvents();
With 10 milliseconds being about the smallest time necessary to get the widget to render correctly.
Does anyone know how to get this to work without the time delay, or know why the delay is necessary?
To test Qt GUI application you need at least QApplication instance and event loop being processed. The fastest way is just use QTEST_MAIN macro, this answer explains in a nice way what it does exactly. However, to have more flexibility (e.g. to use GTest, GMock) you can also simply create QAplication instance in your tests main (no need to call exec).
Then, to have the events processed, you should invoke QTest::qWait. This will process your events for the specified amount of time. It is a good practice to use qWaitFor which accepts a predicate - this way you avoid race conditions in your tests.
In the particular scenario, when you expect some signal to be emitted, you can also use similar functionality of QSignalSpy::wait.
Small example when we want to wait until some parameters are passed from one item to another:
QSignalSpy spy(&widget1, &Widget1::settingsChanged);
widget2->applySettings();
ASSERT_TRUE(spy.wait(5000));
// do some further tests based on the content of passed settings
Why don't you want to have the application run exec ? The process of displaying a widget is not "static". You don't "draw" the widget on the screen, but rather you have an application that listen for various events and receives draw events from the windowing manager. The application can only draw the widget when the windowing manager asks it to.
The reason your second code works is that you wait sufficiently long for the windowing manager to have sent the "draw" request in your conditions. This does not guarantee it will always work.
If you want to guarantee the display of the widget, you need to start a loop and wait until you have received at least one draw event, but even that isn't foolproof.
As expertly described by Vincent Fourmond, widgets are not a one-off deal. The GUI is non-blocking and for this, it needs to run in an event loop.
The exec() method starts this event loop which you mimicked by polling.
While it is possible to combine Qt's event loop with other event loops, I would recommend you a simpler solution:
Proceed your program within the event loop by calling a method when it starts. Find an excellent answer here on how to do this: https://stackoverflow.com/a/8877968/21974
As you mentioned unit testing, there is also a signal you can use for doing checks at the end of the lifecycle (before widgets are destroyed): QApplication::aboutToQuit. This will happen when the last window is closed (programmatically or by the user).

How to call a function after an animation ends?

So I've recently started dabbling a bit with the Qt animation framework and I'd say everything goes pretty well, however now I'd like to make it so that a function gets called after an animation finishes, is this possible?
I've already tried executing the function after the animation starts, however this doesn't seem to work (I presume because Qt animations are ran on a separate thread)
The way I've tried this is very simply like this:
AnimIn->setDuration(500);
AnimIn->setStartValue(0.f);
AnimIn->setEndValue(1.f);
AnimIn->setEasingCurve(QEasingCurve::InCubic);
AnimIn->start();
MyFunction();
I've tried looking through the Qt documentation but to no avail, seeing that pretty much everything about animation and Qt is in QML which I don't use.
You'll need to listen to the finished() signal from your animation. Here's how you'd connect the signal:
QObject::connect(AnimIn, &QAbstractAnimation::finished, this, &YourClass::OnAnimFinished);
where OnAnimFinished() is obviously a slot in your current class. When the animation finishes, the signal will be emitted and the slot will be invoked. Then in the body of the OnAnimFinished() function you can call MyFunction().

What does QTimer::singleShot(0, object SLOT(obj_slot())) do?

I'm beginner learning Qt, and trying to understand a Qt provided example for download operation. In downloadmanager.cpp, a member function is the following:
void DownloadManager::append(const QUrl &url)
{
if (downloadQueue.isEmpty())
QTimer::singleShot(0, this, SLOT(startNextDownload()));
downloadQueue.enqueue(url);
++totalCount;
}
I'm confused to why, if downloadQueue is empty, it will need to activate the startNextDownload() before adding the url. (note that: startNextDownload() ends the program if the downloadQueue is empty)
I'm unsure why: QTimer::signleShot(x, y, z) has been used at all. As I understand it to be, a timer that activates the slot with delay of 0 millisecond.
I could not figure out from looking at Qt Assistant whether singleShot is a one time setup for repeated activation to the slot at given millisecond interval or whether it is one time
Clarification:
I'm a beginner and in examples like:
statement1;
statement2;
I'm used to seeing statement1 running and finishing before moving on to working on statement2. But trying to learn Qt and reading the given example, I see the SLOT(startNextDownload()) being activated after downloadQueue.enqueue(url); has taken place. I am trying to understand why does this work.
This queues a callback in the message queue.
The timer immediately elapses, and a message is posted to the message queue. When the process reaches the main loop for the next time, the startNextDownload() function is called. By this time, the URL is in the queue.
The startNextDownload() function is called from the dispatch context, where it is safe to change window contents. This way, the DownloadManager class can be used from a multithreaded application, where the thread starting the download might be running concurrently with the handler for a Paint event. By invoking it from the same thread that would handle Paint events you can be sure that no such event is being processed, and you can update widgets safely.
If a widget needs to be repainted afterwards, it then asks to be repainted, and the OS will send a Paint event if the widget is currently visible.
Answer to current question title
Every call to QTimer::singleShot(...) is executed on the event loop of the thread where it is invoked **. If invoked from the main thread, it'll be the event loop started with app.exec().
According to the Qt-Network-Manager-Example, this function is called after the network-manager is filled with the URL's so the single-shot will be processed after the queue has been completely filled. Poorly the qt documentation isn't that clear about this topic yet, so for more information about event processing etc please look here.
Answer for old question title
Before I start, the timer is for having the download in an extra thread. So the GUI keeps responsive.
The complete downloadNext() method is recursive. It will be only called once and called till the queue is empty.
See this:
void DownloadManager::append(const QStringList &urlList)
{
foreach (QString url, urlList)
append(QUrl::fromEncoded(url.toLocal8Bit())); //Call for only one URL
...
}
void DownloadManager::append(const QUrl &url)
{
if (downloadQueue.isEmpty())
//I'm only called if the queue is empty! And I will be called after the next line. Not instantly!
QTimer::singleShot(0, this, SLOT(startNextDownload()));
downloadQueue.enqueue(url);
++totalCount;
}
After the queue is empty each method returns and at least the message that the download is done will be printed.
So why does this work?
Please see first chapter below.
you can understand things about Class QTimer before you end up with a solution as you desire, please have a look here for your understanding

how to change GUI while processing

I am new to Qt Programming, but I have basic on C++.
I want to update my GUI while it is processing, example:
while (....)
{
do some calculation...
if (condition fulfill)
change the color of label.
}
However, I realise that I failed to get the result I want (update the GUI while processing). The GUI will only update after the while loop.
Why is it so? Anyone can help?
In addition, I wish to "slower" the color change since the processing is too fast and I can't see the animation. Any idea to do it?
Thank you very much!
Clarification:
Actually I wish to update the GUI while I am processing...Meaning that, if I have 100 iteration, after each iteration I wish to update the GUI immediately.
Use a QTimer. This will allow you to control the speed of your animation and keep your UI responsive.
You have to place your processing code to another thread and update the gui, because like this GUI will be waiting for your process to end and will refresh after its end
read more here:
http://www.qtcentre.org/threads/41545-How-to-refresh-GUI-while-heavy-processing-is-ongoing
http://www.qtcentre.org/threads/32416-Update-GUI-from-another-thread
Forcing the Qt GUI to update
You don't necessarily need a thread.
Calling QApplication::processEvents() will process pending events, including any redraws you may have caused during your processing.
If you wish to animate the color to indicate that the system is currently working, you might want to use QApplication::setOverrideCursor to show a waitCursor, or a QProgressDialog instead.

QT Repaint/Redraw/Update/Do Something

I'm New to QT. I understand that you can force a display refresh, but I've pulled all my hair out trying to figure out how. Here is what I'm specifically trying to do.
I press a button (onClick signal event), which runs code that changes an image (QLabel) on the display, waits for input, and then proceeds by changing a new image (different QLabel). I've tried everything and the display doesn't refresh until the onclick signal event code is complete. Right now, I'm not waiting for user input, I'm using usleep(~500 ms) for testing purposes.
From what I read, QT is event driven meaning that I'm basically creating a bunch of events, that get put in a que, and executed when the (onClick signal event) returns to the (main loop)/(event handler). I don't want to wait until the function is complete, it's going to make programming extremely painful if I have to accomplish this routine entirely based on events.
How can I force the QLabel pixmap to refresh. I've tried everything. Below is all the code I have tried in my onClick signal event handler. (upButton is the name of the QLabel which is a pixmap)
update();
repaint();
ui->upButton->setUpdatesEnabled(TRUE);
update();
repaint();
QPaintEvent paintevent(ui->upButton->childrenRegion());
QPaintEvent * test = &paintevent;
paintEvent(test);
this->changeEvent(test);
ui->upButton->update();
ui->upButton->repaint();
ui->upButton->repaint(ui->upButton->childrenRegion());
repaint();
QApplication::sendPostedEvents();
this->parentWidget()->update();
usleep(100000);
As you can see, I'm just shooting in the dark at this point. I've tried to look at sample code and do all my homework, but I'm lost. Appreciate any help, advice, and or sample code.
I was using sleep to emulate a brief amount of time the computer was waiting for something to happen.
As I stated in my question, I didn't want to use events because it's a whole lot of unnecessary work to accomplish something extremely simply.
Also, the 'event' that needs to take place for the program to continue, is a USB event. Since I'm using an HID class device, there is no way to set an event to happen without a wait loop. USB HID classes don't permit setting interrupts, the OS claims the device.
I managed to get the above to work. I walked through the debugger and noticed the display would refresh before the sleep function. Running the program independently, I got random results with the display refreshing 1% of the time. I got rid of the sleep function, and added some other code in it's place to emulate a delay, and it was fine.
Just for everyone's knowledge, this is possible, it's not forbidden, and it's easy to do with the following:
qApp->processEvents();
qApp is a global external variable in the QApplication header.
Because this USB event is making my flow tricky, I stumbled upon the QWaitCondition Class. I was going to start a process waiting for the USB event. I would wait until the process releases the wait condition for my routine to continue.
But if anyone thinks this is a bad idea, please, speak out. I really do appreciate your feedback PiedPiper and Hostile Fork.
Thank you.
I noticed sometimes when you have multiple layered widgets, or widgets inside of widgets it helps to call their repaint() events.
For example
this->repaint();
this->parentWidget()->repaint();
this->parentWidget()->parentWidget()->repaint();
This is far easier then pushing out any processing to another Thread, or creating additional event handlers.
You shouldn't be waiting for input in your event handler. You need to rethink the logic of your program to use events the way they were intended. All the update() and repaint() calls in your code are unnecessary if you return to the event loop.
If i understood correctly, you have a slot and in this slot, you update the image shown in a QLabel. But you want this change to be displayed before the slot finishes.
If that is the case, issue an update() event, and call qApp->processEvents(). This method processes events that are waiting in the event queue and then returns, therefore this may be what you are after.
PS: an update() may not be necessary at all, i am not sure.