I'm building a real-time system in Qt. Every 20 ms I need to paint 5 points in a QFrame to make the painting of a signal looks like real time. When I only paint the signal in the QFrame, the call to paintEvent() is done with the desired frequency, 20 ms. But when I focus on another QWidget or when I show another window (in other words, when I perform another painting action that isn’t very simple) the call to paintEvent() starts to slow down and the samples of the signal are accumulated.
The call to the function paintEvent() is made from the call to the function update() of the QFrame every 20 ms. In Qt you cannot separate the painted gui into threads. Therefore, the call to paintEvent() runs in the same thread as the call to the functions responsible for the other actions of painting in the gui. This causes that when focusing another QWidget, when the processing associated with painting a box in the QWidget is delayed, the event of painting the signal is delayed.
The question is whether there is any way to make the event to paint signal priority, so that paintEvent() is called with the same frequency, no matter what it is done in the gui. I use repaint instead of update, because in the help of Qt it says that repaint makes the direct call to paintEvent(), but the result was disastrous.
Any other idea will be of great help.
Related
I am planning a Qt simulator, i.e. a GUI surface in one thread receives the signals
emitted from another thread (this other thread is suspended -not resumed- while processing),
while the main program is essentially just for starting the two threads.
I found
How to emit cross-thread signal in Qt?
which works (after adding a missing semicolon), but after calling
MyObject::MySlot (i.e. printing the text ""slot called"), the control goes to
CThread2::exec() and is not given back CThread1::run(), which would emit further signals.
It looks like its event loop keeps waiting for another event.
I do not want either thread to quit: CThread1 is expected to emit a series of signals,
and CThread2 is expected to process them.
What is wrong here? (the MWE is provided in the reply part of the thread above)
Another question, how a GUI surface can be moved to a thread, given that
http://doc.trolltech.com/4.6/qthread.html
states that
"Note, however, that it is not possible to use any widget classes in the thread."
It is known that QWidget::paintEvent is triggered automatically the moment widget becomes visible or any event from the basic window happens. What should I do if I only want the paintEvent to be issued in response to update()?
It'd make no sense for a paintEvent not to be issued whenever the widget needs to be painted. Your reason to demand such an option means that you're trying to use the Qt API in a way it wasn't meant to be used. I can't quite imagine yet a particular design that would lead you to such use, sorry about that.
So, the only thing I can tell you is how you'd use update(). The idiomatic way of handling widget updates is as follows:
The source of data that the widget uses is updated. For example, the text or some variable affecting the visible contents is changed. Often this data is a Q_PROPERTY of the widget. The setter function is updating the member variable that stores the value and calls update(). The setter should not perform any expensive computations - they should be deferred until the paint event.
If the properties are changed multiple times before the event loop has a chance to run, the update events get coalesced. Internally, a call to update() results in posting an event to the event queue of the GUI thread. If there already is an update event in the queue for the given widget, the events get coalesced. The following invariant is preserved: at any given time, there can only be one update event for any particular widget in an event queue.
When the control returns to the event loop, the update event gets dispatched to the widget, ending up in calling your reimplementation of QWidget::paintEvent(...). This implementation should do the calculations necessary to paint the widget, and do the actual painting. If the calculations are extensive, they should be relegated to a worker thread.
Example
Let's say an application is receiving data from a serial port, modeled as a QIODevice (a QSerialPort is one). You could do as follows:
Connect QIODevice's readyRead signal to a slot in a parser QObject.
The slot receives and parses the data. It then emits a signal with processed data (for example, a vector of floating point values). This signal is connected to a newData slot in the widget.
The newData slot adds the data as-is to a queue, and schedules an update(). This is very fast if you're using Qt's data structures, or if your data class is modeled after them and uses implicit sharing with copy-on-write.
The update() dequeues all data sets and plots them. The QWidget::scroll() method comes handy for scrolling plots.
In QWidget, rather than being signals, mouse and paint and other events are virtual functions to be overloaded. Why is this the case, rather than being consistent?
Although I can't find anything within Qt's documentation that states their motivations for using virtual functions for events, I can guess:
Signals and slots can be nice to work with, but there's overhead associated with them (see, the answer to this question). Since events are triggered quite frequently, the use of signals and slots could carry quite a performance penalty.
Some event handlers need to return values. Returning a value from a slot back to the signal emitter is not officially supported (though see this question), which means that they wouldn't be appropriate.
Signals emitted from QWidget may not make sense from a design point-of-view. If I create my own widget derived from QWidget, why have signals emitted from my widget that just connect back to slots within the widget itself? This also has the danger of breaking encapsulation since signals are always "public".
Even if none of the above were true, there would still be quite a few architectural questions raised by trying to use signals for events. For example, a single event is often passed to multiple different objects (for example, in the case where some objects don't wish to process the event). In this scenario, which object emits the signal indicating that the event has taken place? It's certainly not the target of the event (i.e., the widget, as you've implied above). It would have to be some other global object. But if that were true, we would likely just implement virtual slots on every widget to handle the signal. This essentially just gets us back to where we started with virtual functions!
I am loading a set of 100 images to a QTableWidget. Since it takes about 4 seconds loading, I want to show a progress bar (customised one) with activity indicators or spinner etc. How could I update the GUI and the progress bar simultaneously, by signals & slots, and after loading the images?
Your event loop is busy with your main task, so it can't process your request. All slots will be called after event loop is free. Your options are:
Move slow processing to another thread. That may be not an option here because you can't interact with Qt's widgets in non-main thread.
Call QApplication::processEvents() each time when you want your GUI changes to apply. This is a common and simple solution. This function will execute your slots (if any calls are sheduled), updates GUI and returns execution flow to you.
A better way to load your images would be using a QThread that emits a signal as it processes the images, and connect that signal to a slot in your main widget, here you'll find a couple of examples
I am working on a multi -segment download manager. I want to display the segmentation procedure. QGraphicsScene works fine but , unfortunately it slows the download. Is there any better option, other than using QProgressBars.
I am using QNetworkAccessManager to download files. If I connect the downloadProgress signal of QNetworkManager object to a slot of Main Gui Thread which draws on QGraphicsView, the download speed decreases even upto 10 times in some cases
// a custom progress bar
void Download::showGProgress(int num, float prgrss) //slot
{
prgrss=prgrss/100;
x_coord=(ui->graphicsView_2->width()-3)*prgrss;
for(float b=0;b<=x_coord;b=b+0.5)
{
progress.addRect(0,0,x_coord,y_coord);
}
}
QNetworkAccessManager is not threaded. It is asynchronous, using the current threads eventloop. It is the HTTP requests which it create that are the threaded aspect.
This would explain why anything you do in your main thread could theoretically slow down the operations of the download. Though not necessarily the underlying threaded download itself, but rather the signaling response time that would allow you to have fast feedback about it.
What you should probably do is create your own QThread subclass, and create the QNetworkAccessManager in the run() method. And then create a QEventLoop in the thread and call exec()
In a nutshell, you need to create your own Threaded QNetworkAccessManager.
create your own widget to do what you would like
this is easier than it sounds.
Make a class that subclasses from a QWidget. And in this widget make a Horizontal Sizer that contains 100 Qlabels (store the QLabels in a vector). Give it slots to 'update' the current progress by setting the background color of each QLabel to a different color. This should be fairly easy to do progressively, meaning you store the current 'percentage' as a member variable and then only adjust the fields that are necessary to get to the percentage that you're looking for (This will eliminate some flickering if you were to do it from scratch every time).
Add functions that will switch the sizer to a vertical one instead of a horizontal one to make it even more customizable.
This allows you to get creative in the what you can do for the progress bar as each element could be a different picture, or a different color, or whatever you would like.
Did you try QProgressBar? Maybe you can write a subclass of it to handle your own properties.