QMessageBox show() not displaying text
-
@mrjj are you asking if the sendDiscoveryRequest() routine might be timing out? That's unlikely...it just writes a short byte array to the serial port and flushes it.
-
@mzimmers
Oh, sorry for being unclear,
i mean, do u need to be able to have a timeout on each command if no answer is received ?
Often it goes
SendCMD
OnReplyDo/ TimeOut-> restart sequence.@mrjj I'm still not sure I understand your question, so let me give some supplementary information.
In normal operation, the host forms requests and sends them to the target, then reads a response from the target. Unfortunately, the target also spews out unsolicited (and unwanted messages) when in a certain state. During the first 10-15 seconds of this state, the target will ignore any input from the host. After this 10-15 second period, the target will listen for requests. A discovery request will cause the target to cease sending the (unwanted) debug messages.
Because the messages are binary and encrypted, there's no way of knowing at first glance whether I've received a "real" response, or just the debugger output. My solution is, when the target is in the "resetting" state, send it a discovery request every second, until I get a valid discovery response. THAT is what I'm trying to do with my timer.
I don't "wait" for responses to my requests; I just process any serial input with a slot.
I don't know whether this answers your question or not...
-
@mrjj I'm still not sure I understand your question, so let me give some supplementary information.
In normal operation, the host forms requests and sends them to the target, then reads a response from the target. Unfortunately, the target also spews out unsolicited (and unwanted messages) when in a certain state. During the first 10-15 seconds of this state, the target will ignore any input from the host. After this 10-15 second period, the target will listen for requests. A discovery request will cause the target to cease sending the (unwanted) debug messages.
Because the messages are binary and encrypted, there's no way of knowing at first glance whether I've received a "real" response, or just the debugger output. My solution is, when the target is in the "resetting" state, send it a discovery request every second, until I get a valid discovery response. THAT is what I'm trying to do with my timer.
I don't "wait" for responses to my requests; I just process any serial input with a slot.
I don't know whether this answers your question or not...
@mzimmers
Yes that a very nice explanation.
Its seems like a valid approach.
Sometimes i use a list of small classes to hold each state, and use
virtual function to make sure i dont get too many if structuresBut i wonder one thing
timer.singleShot(1000, this, SLOT(sendDiscoveryRequest()));so you call sendDiscoveryRequest one time. will it then start the timer again?
-
The sendDiscoveryMessage() call is a "kick start" to the communications process. One of two things will happen:
- the target is in running state, and will respond with a valid response. In this case, no new timer is desired.
- the target is in resetting state, and will not respond, BUT will continue to send those spurious debug messages. When it sends one of these, the routine the above code is in is invoked (as a slot).
So, in either case, the host will receive some input from the target, and normal processing can continue.
These debug messages can come very quickly, and I don't wish to respond to each with a discovery request. This is the purpose of the timer -- to "gate" my requests. But...it's not working, as timer.isActive() never returns true.
-
The sendDiscoveryMessage() call is a "kick start" to the communications process. One of two things will happen:
- the target is in running state, and will respond with a valid response. In this case, no new timer is desired.
- the target is in resetting state, and will not respond, BUT will continue to send those spurious debug messages. When it sends one of these, the routine the above code is in is invoked (as a slot).
So, in either case, the host will receive some input from the target, and normal processing can continue.
These debug messages can come very quickly, and I don't wish to respond to each with a discovery request. This is the purpose of the timer -- to "gate" my requests. But...it's not working, as timer.isActive() never returns true.
- timer.isActive() never returns true.
Well if it takes more than 1 sec before the containing slot is called again then is it then not true that timer.isActive() is false?
also the single shot might not even set active. maybe only start() does.
(just speculating)
-
- timer.isActive() never returns true.
Well if it takes more than 1 sec before the containing slot is called again then is it then not true that timer.isActive() is false?
also the single shot might not even set active. maybe only start() does.
(just speculating)
@mrjj said in QMessageBox show() not displaying text:
Well if it takes more than 1 sec before the containing slot is called again then is it then not true that timer.isActive() is false?
If it takes more than 1 second (which it never does), the isActive should report false, and a new singleShot should be called. At least that's what I'm attempting to do.
also the single shot might not even set active. maybe only start() does.
(just speculating)Interesting...I'll replace the singleShot with a conventional timer and report back.
- timer.isActive() never returns true.
-
@mrjj said in QMessageBox show() not displaying text:
Well if it takes more than 1 sec before the containing slot is called again then is it then not true that timer.isActive() is false?
If it takes more than 1 second (which it never does), the isActive should report false, and a new singleShot should be called. At least that's what I'm attempting to do.
also the single shot might not even set active. maybe only start() does.
(just speculating)Interesting...I'll replace the singleShot with a conventional timer and report back.
singleShot
is a static function, it callssetSingleShot(true)
and thenstart()
. As this function doesn't really require an object it also does not modify your object in any way, effectively you're callingQTimer::singleShot
.PS.
Use like this:timer.setSingleShot(true); QObject::connect(&timer, &QTimer::timeout, this, &WhateverYourClassIsNamed::sendDiscoveryRequest); // ... if (devState == RESETTING) { if (timer.isActive()) // only do one at a time. qDebug() << "\t\ttimer already queued."; else { timer.start(1000); qDebug() << "\t\tqueueing timer."; } }
-
OK, I found why the timer wasn't working for me. It turns out I defined the QTimer * variable twice: once as a member of my Worker class, and once again in the Worker constructor. General hilarity ensued.
I'm not saying this wasn't my fault, but I'd have expected the damn compiler to at least give me a warning when I did this.
Thanks to all for the help on the QTimer. Now that my communications sequence is intact, I can review my approach to the original problem with the QMessageBox. I'll report back when I have something.
-
OK, I found why the timer wasn't working for me. It turns out I defined the QTimer * variable twice: once as a member of my Worker class, and once again in the Worker constructor. General hilarity ensued.
I'm not saying this wasn't my fault, but I'd have expected the damn compiler to at least give me a warning when I did this.
Thanks to all for the help on the QTimer. Now that my communications sequence is intact, I can review my approach to the original problem with the QMessageBox. I'll report back when I have something.
@mzimmers said in QMessageBox show() not displaying text:
I'm not saying this wasn't my fault, but I'd have expected the damn compiler to at least give me a warning when I did this.
Not a thing that warrants a warning. Shadowing is a normal feature of the language, and you can see it quite a lot in my code. Without this I'd get a ton of warnings for correct usage of a valid language construct. For example for a generic
QObject
subclass (a situation that happens all the time):class MyClass : public QObject { public: MyClass(QObject * parent = nullptr) //< `parent` shadows QObject::parent() : QObject(parent) { } };
Or even more elaborate:
void QMpiCompoundRequestPrivate::requestFinished(QMpiRequest * child) { if (!subrequests.remove(child)) return; Q_Q(QMpiCompoundRequest); emit q->finished(child); if (subrequests.size() == 0) emit q->QMpiRequest::finished(); }
See how the second signal emission is done. That's because in the derived class (
QMpiCompoundRequest
) there's a function that shadows the base class' (QMpiRequest
) method (even though with different set of parameters). So in this case you must be explicit which function exactly you're calling. -
@mzimmers said in QMessageBox show() not displaying text:
I'm not saying this wasn't my fault, but I'd have expected the damn compiler to at least give me a warning when I did this.
Not a thing that warrants a warning. Shadowing is a normal feature of the language, and you can see it quite a lot in my code. Without this I'd get a ton of warnings for correct usage of a valid language construct. For example for a generic
QObject
subclass (a situation that happens all the time):class MyClass : public QObject { public: MyClass(QObject * parent = nullptr) //< `parent` shadows QObject::parent() : QObject(parent) { } };
Or even more elaborate:
void QMpiCompoundRequestPrivate::requestFinished(QMpiRequest * child) { if (!subrequests.remove(child)) return; Q_Q(QMpiCompoundRequest); emit q->finished(child); if (subrequests.size() == 0) emit q->QMpiRequest::finished(); }
See how the second signal emission is done. That's because in the derived class (
QMpiCompoundRequest
) there's a function that shadows the base class' (QMpiRequest
) method (even though with different set of parameters). So in this case you must be explicit which function exactly you're calling.@kshegunov thanks for the explanation. I had never seen shadowing before, probably because I'd done very little work with derived classes. Good stuff to know going forward.