I am making an application in QT. I use QExtSerialPort to receive data from the serial port of my comp (whenever the readyread() signal is emitted). I also have some timers running doing other stuff at certain intervals. Now I noticed that when the timers are turned on, not all the data of the readyread signal is emitted a lot less, then when the timers are not turned on. Is there a way in QT to make sure that all the data of the serial port is received? Maybe by setting a high priority to the readyread event or something like that?
There is difference between signal-slot connections and event system. Signal emitting and slot triggering are not separate things — when signal is emitted, connected slots begin to work. So they (signals) can't be lost.
All events are sent through application, and also are received, but it can happen later. When control returns to the main event loop, all events that are stored in the queue, will be processed.
If you are posting events yourself, you can use
static void QCoreApplication::postEvent ( QObject* receiver, QEvent* event, int priority ); method.
Events are sorted in descending priority order, i.e. events with a high priority are queued before events with a lower priority. The priority can be any integer value, i.e. between INT_MAX and INT_MIN, inclusive; see Qt::EventPriority for more details. Events with equal priority will be processed in the order posted.
Related
I'm new to Qt and currently learning to code with QTcpServer and QTcpSocket.
My code to process data is like
Myclass()
{
connect(&socket, &QTcpSocket::readyRead, this, &MyClass::processData);
}
void MyClass::processData()
{
/* Process the data which may be time-consuming */
}
Is it the correct way to use the signal like that? As I'm reading the documentation that in the same thread the slot is invoked immediately, which means if my processing work hasn't finished and new data comes, Qt will pause on the current work and enter the processData() again. That is not exactly what I want to do, So should I QueueConnection in the signal/slot connection?
Or could you please provide some good methods that I should adopt in this case?
Qt will not pause your current work when data comes in, it will call processData() only when the event loop is free and waiting for new events.
so, when your application is busy executing your code, the application will appear to be unresponsive, because it can't respond to external events, so processData() won't get called if some data is received on the socket until the current function (that may contain your heavy code) returns, and the control is back in the event loop, that has to process the queued events (these events may contain the received data on the socket, or the user clicks on some QPushButton, etc) .
in short, that's why you always have to make your code as short and optimized as possible, in order not to block the event loop for a long time.
With the event delivery stuck, widgets won't update themselves (QPaintEvent objects will sit in the queue), no further interaction with widgets is possible (for the same reason), timers won't fire and networking communications will slow down and stop. Moreover, many window managers will detect that your application is not handling events any more and tell the user that your application isn't responding. That's why is so important to quickly react to events and return to the event loop as soon as possible!
see https://wiki.qt.io/Threads_Events_QObjects
What happens if I start a QTimer firing at regular intervals but the slot reacting to the timeout signal blocks the main loop for longer than another timer interval. Will the timout signals then be stacked on the Qt main event loop and processed one after another as soon as the event loop runs again?
If yes, what happens if multiple timeout events are stacked on the event queue but the timer is deactivated before they can be processed?
If QTimer object and the signal receiver belong to one thread, no queuing happens. timeout() signal will not (and cannot) be sent again until control flow goes to the event loop, and that won't happen until the slot is completely executed (unless QApplication::processEvents is called in the slot, which can turn this into a mess). But if your slot was being executed longer than the timer's interval, timeout() will be sent once the event loop is free, so your slot will be immedately called again. But QTimer will not send two timeout() signals closer than its interval.
If QTimer is in another thread, and that thread is not busy with something else, it will send timeout() signals regularly regardless of how well slot in another thread goes. This is where Qt's signal-slot system comes in. And it will queue emitted signals. If your slot is slow, it will call it multiple times without delay. If you stop the timer, it won't undo already sent signals and the slot may be called multiple times after it. Additionally, if you stop the timer, there is always a possibility that another signal is being sent just in this moment and your slot will be called once again.
If you want strict intervals between slot invocations regardless of the slot's executing time, you should use single-shot timers. At the end of your slot, start a single-shot timer. When it's timed out, it will invoke your slot and deactivate, so you can start it again at the end of the slot.
If your program's logic depends on the timer's state, you should check that the timer is active at the start of your slot. It's not guaranteed that the timer is active when the slot is being executed.
I am developing a consequent program which is very sensitive to time (based on delayed video streams), and since I'm not sure about how the signals and slots are implemented within Qt, I don't know when they are executed. Are they really executed in real time like callbacks would do, or are they processed before the next iteration of some kind of main loop?
My question would be about timers in particular: when a timer times out (which must be another thread), does it connect to the signal "instantaneously" (next instruction for example) nearly like an interrupt would do, or does it wait for the end of some loop?
Thanks for your insight,
Regards,
Mister Mystère
The last argument of QObject::connect is the connection type, which determines when slot will be executed. From the documentation:
Qt::AutoConnection - If the signal is emitted from a different thread than the receiving object, the signal is queued, behaving as
Qt::QueuedConnection. Otherwise, the slot is invoked directly,
behaving as Qt::DirectConnection. The type of connection is determined
when the signal is emitted.
Qt::DirectConnection - The slot is invoked immediately, when the signal is emitted.
Qt::QueuedConnection - The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in
the receiver's thread.
Qt::BlockingQueuedConnection - Same as QueuedConnection, except the current thread blocks until the slot returns. This connection type
should only be used where the emitter and receiver are in different
threads.
http://woboq.com/blog/how-qt-signals-slots-work.html
This seems to be quite a good description, though I haven't read it in detail.
Main point: there's direct connections and deferred connections. Direct connections are executed immediately.
You can be quite sure the timer is not implemented in a different thread but instead is handled inside the event loop. Which means that when the timer fires, it is instantly connected. However the granularity for the timer to fire is your main problem.
If your timer were to emit the signal in a different thread, the slot would be called in the thread the receiving object belongs to. Which means that it would be deferred to the event loop. (As you can see it would not help to have the timer operate in a thread of its own.)
And additionally in Qt5 you can set QTimer's precision: Qt::TimerType
It is hard for me to understand the difference between signals and events in Qt, could someone explain?
An event is a message encapsulated in a class (QEvent) which is processed in an event loop and dispatched to a recipient that can either accept the message or pass it along to others to process. They are usually created in response to external system events like mouse clicks.
Signals and Slots are a convenient way for QObjects to communicate with one another and are more similar to callback functions. In most circumstances, when a "signal" is emitted, any slot function connected to it is called directly. The exception is when signals and slots cross thread boundaries. In this case, the signal will essentially be converted into an event.
Events are something that happened to or within an object. In general, you would treat them within the object's own class code.
Signals are emitted by an object. The object is basically notifying other objects that something happened. Other objects might do something as a result or not, but this is not the emitter's job to deal with it.
My impression of the difference is as follows:
Say you have a server device, running an infinite loop, listening to some external client Events and reacting to them by executing some code.
(It can be a CPU, listening to interrupts from devices, or Client-side Javascript browser code, litsening for user clicks or Server-side website code, listening for users requesting web-pages or data).
Or it can be your Qt application, running its main loop.
I'll be explaining with the assumption that you're running Qt on Linux with an X-server used for drawing.
I can distinguish 2 main differences, although the second one is somewhat disputable:
Events represent your hardware and are a small finite set. Signals represent your Widgets-layer logic and can be arbitrarily complex and numerous.
Events are low-level messages, coming to you from the client. The set of Events is a strictly limited set (~20 different Event types), determined by hardware (e.g. mouse click/doubleclick/press/release, mouse move, keyboard key pressed/released/held etc.), and specified in the protocol of interaction (e.g. X protocol) between application and user.
E.g. at the time X protocol was created there were no multitouch gestures, there were only mouse and keyboard so X protocol won't understand your gestures and send them to application, it will just interpret them as mouse clicks. Thus, extensions to X protocol are introduced over time.
X events know nothing about widgets, widgets exist only in Qt. X events know only about X windows, which are very basic rectangles that your widgets consist of. Your Qt events are just a thin wrapper around X events/Windows events/Mac events, providing a compatibility layer between different Operating Systems native events for convenience of Widget-level logic layer authors.
Widget-level logic deals with Signals, cause they include the Widget-level meaning of your actions. Moreover, one Signal can be fired due to different events, e.g. either mouse click on "Save" menu button or a keyboard shortcut such as Ctrl-S.
Abstractly speaking (this is not exactly about Qt!), Events are asynchronous in their nature, while Signals (or hooks in other terms) are synchronous.
Say, you have a function foo(), that can fire Signal OR emit Event.
If it fires signal, Signal is executed in the same thread of code as the function, which caused it, right after the function.
On the other hand, if it emits Event, Event is sent to the main loop and it depends on the main loop, when it delivers that event to the receiving side and what happens next.
Thus 2 consecutive events may even get delivered in reversed order, while 2 consecutively fired signals remain consecutive.
Though, terminology is not strict. "Singals" in Unix as a means of Interprocess Communication should be better called Events, cause they are asynchronous: you call a signal in one process and never know, when the event loop is going to switch to the receiving process and execute the signal handler.
P.S. Please forgive me, if some of my examples are not absolutely correct in terms of letter. They are still good in terms of spirit.
An event is passed directly to an event handler method of a class. They are available for you to overload in your subclasses and choose how to handle the event differently. Events also pass up the chain from child to parent until someone handles it or it falls off the end.
Signals on the other hand are openly emitted and any other entity can opt to connect and listen to them. They pass through the event loops and are processed in a queue (they can also be handled directly if they are in the same thread).
I'm writing a simple port communication program. On the GUI side of the application I have a panel with 12 buttons that send signals to the parallel port interface. The communication with the port is done and working. What I need now is an automatic switching between buttons. The goal is to start kind of screensaver that will periodically activate the buttons and send signals to the port. In practice it would look like this: a timer is started for 2 minutes and if any event occurs it is restarted. Otherwise if timer reaches timeout() the qt signal is emitted, the switching begins and the buttons are automatically click()'ed with the interval of 5 seconds.
My questions are:
How to enable a starting timer that will be reseted if any key/mouse event occurs?
How to define a transition between the buttons with a sleep interval?
Use QTimer for the timing part.
For the "screen-saver"-like one, create a single-shot timer, connect it to a custom slot of yours, and set it's interval to two minutes.
activeTimer = new QTimer(this);
activeTimer->setInterval(2*60*1000);
activeTimer->setSingleShot(true);
connect(activeTimer, SIGNAL(timeout()), this, SLOT(activateAutoClick()));
activeTimer->start();
In that custom slot, start a second, non-single shot timer connected to a second custom slot
void YourThing::activateAutoClick() {
autoTimer->setInterval(5*1000);
autoTimer->setSingleShot(false);
connect(autoTimer, SIGNAL(timeout()), this, SLOT(autoClick()));
autoTimer->start();
}
And do whatever you want in terms of sending signals to your port in autoClick.
To cancel either timer, simply call their stop() method/slot.
To implement the "screen-saver" behavior, create a function that:
Calls autoTimer->stop() to disable auto clicks
Calls activeTimerr->start(2*60*1000) to restart that one
And call that function whenever needed. You can do that from already existing slots for your buttons, or reimplement event handlers like QWidget's mouseMoveEvent, keyPressedEvent and such. (Be sure to read the documentation for the handlers, some require specific preparation.)