qt inherited signal won't reach to slot - qt

here's the code of my problem
class Base : QThread
{
Q_OBJECT
virtual void run() = 0;
signals:
void Ping(int);
};
class Derived : public Base
{
void run()
{
emit Ping(42);
}
}
the signal(42) won't reach/call to slots. what's wrong?
thanks in advance.

Did that 100 times, it does work. Are you sure your base class is properly MOC'ed ? (i.e. defined in a file contained in HEADERS section of .pro) Also when connecting your signal, check the return status of QObject::connect (it's a boolean). A good practice is something like that
bool r=false;
r=QObject::connect(pObj1,SIGNAL(signalStuff()),pObj2,SLOT(gotStuff()));
Q_ASSERT(r);
As Liz noticed, if something went wrong in your connect, you can check the traces to know what happened.
I can also note :
you don't have to redefine run in your base class, it's already defined by QThread
Common pitfall with QThread: Base class and Derived class belong to the thread which created them, not in the newly created thread
you don't connect your signal to any slot in your sample, so it won't trigger anything (I suppose it's done elsewhere)
your class Derived lacks the final ;
EDIT:
Edited to take into account liz' interesting comment.

I came upon the same problem but managed to find solution. The problem in my case wasnt the inheritance (even tho i did emit from derived class).
The problem was the code calling emit signal was execute BEFORE the code connecting signal with slot. Therefor both signal was emitted and signal-slot connection worked fine, but the code in the slot wasnt executed because emit happened before connecting the slot to signal.
Maybe that helps someone in the future.

I think you are trying to connect signal and slot from different threads.
Did you read this article?

Related

Qt Signals and Slots with Boost::smart_ptr

So what I am trying to do is use Qt signals and slots to pass around an image through a smart_ptr so that it will delete itself when everything that needs to use the data is done accessing it.
Here is the code I have:
Class A, inherits QObject:
signals:
void newImageSent(boost::shared_ptr<namespace::ImageData> &image);
Class B, inherits QObject:
public slots:
void newImageRecieved(boost::shared_ptr<namespace::ImageData> &image)
{
// Manipulate Image
}
Connection Code:
QObject::connect(classAPtr.get(),
SIGNAL(newImageSent(boost::shared_ptr<namespace::ImageData>)),
classBPtr.get(),
SLOT(newImageRecieved(boost::shared_ptr<namespace::ImageData>)),
Qt::QueuedConnection);
When I try to do the connection is always returns false though, so is there something I am missing?
In a queued connection the signal is queued in the event loop and its parameters are copied.
Therefore the slot is not directly executed.
To make copying possible you have to register the type via qRegisterMetaType, see also here.
Since you are using shared pointers easiest solution would be to transmit them by value, then you would not have to bother with the references as Frank Osterfeld pointed out.
The way you create the connection is string based and as result is easy to get wrong, especially when namespaces are involved.
Using typedef would ease the pain a little and make it easier to spot errors.
For example you could do
typedef boost::shared_ptr<namespace::ImageData> ImageDataPtr;
and use ImageDataPtr from then on.
Especially on registering the type as meta type which you have to do since you are using a queued connection.
If you are using Qt5 then you can rely on the new connection syntax which ensures correctness during compilation as it does not rely on string comparisons:
QObject::connect(classAPtr.get(), &A::newImageSent,
classBPtr.get(), &B::newImageRecieved,
Qt::QueuedConnection);

How to disconnect a signal with a slot temporarily in Qt?

I connect a slot with a signal. But now I want to disconnect them temporarily.
Here is part of my class declaration:
class frmMain : public QWidget
{
...
private:
QTimer *myReadTimer;
...
private slots:
void on_btnDownload_clicked();
...
};
In the constructor of frmMain, I connect myReadTimer with a slot so that ReadMyCom will be called every 5 seconds:
myReadTimer=new QTimer(this);
myReadTimer->setInterval(5000);
connect(myReadTimer,SIGNAL(timeout()),this,SLOT(ReadMyCom()));
But, in slot on_btnDownload_clicked. I don't want myReadTimer to emit any signal in on_btnDownload_clicked's scope. So I want to disconnect them at the beginning of on_btnDownload_clicked and reconnect them in the end. Like this:
void frmMain::on_btnDownload_clicked()
{
//some method to disconnect the slot & singal
...//the code that I want myReadTimer to leave me alone
//some method to reconnect the slot & singal
}
I searched in Stackoverflow and got some answer like call the QObject destructor. But I don't know how to use it.
I also tried to use disconnect, like:
QMetaObject::Connection myConnect;
myConnect=connect(myReadTimer,SIGNAL(timeout()),this,SLOT(ReadMyCom()));
...
disconnect(& myConnect);
But it still not work. So could any one help me how to do this?
There is a very nice function in QObject that comes in handy every now and again: QObject::blockSignals()
Here's a very simple fire-and-forget class that will do what you want. I take no credit for it's design, I found it on the internet somewhere a long time ago. Be careful though, it will block all signals to all objects. If this is not what you want, you can modify the class to suit your needs.
class SignalBlocker{
public:
SignalBlocker(QObject *o): object(o), alreadyBlocked(object->signalsBlocked()){
if (!alreadyBlocked){
object->blockSignals(true);
}
}
~SignalBlocker() {
if (!alreadyBlocked){
object->blockSignals(false);
}
}
private:
QObject *object;
bool alreadyBlocked;
};
Usage, in your case, becomes trivial
void frmMain::on_btnDownload_clicked()
{
SignalBlocker timerSignalBlocker(myReadTimer);
...//the code that I want myReadTimer to leave me alone
// signals automatically unblocked when the function exits
}
UPDATE:
I see that from Qt 5.3, a very similar class has been offically added to the API. It does a similar job as the one above with a slightly bigger feature-set. I suggest you use the official QSignalBlocker class instead in order to keep your codebase up-to-date with any API changes.
Usage, however, remains exactly the same.
Disconnect/reconnect syntax
There are many ways to call disconnect, depending on exactly what you want disconnected. See the QObject documentation page for an explanation of how they work.
Here's an example using 0 to mean "disconnect all slots."
void frmMain::on_btnDownload_clicked()
{
// disconnect everything connected to myReadTimer's timeout
disconnect(myReadTimer, SIGNAL(timeout()), 0, 0);
...//the code that I want myReadTimer to leave me alone
// restore the connection
connect(myReadTimer,SIGNAL(timeout()),this,SLOT(ReadMyCom()));
}
Or you can specify the exact signal-slot pair to disconnect by copying your 'connect' syntax, like this:
disconnect(myReadTimer,SIGNAL(timeout()),this,SLOT(ReadMyCom()));
Stopping the timer
Since you're working with a timer, this may be simpler:
void frmMain::on_btnDownload_clicked()
{
// stop the timer (so you won't get any timeout signals)
myReadTimer->stop();
...//the code that I want myReadTimer to leave me alone
// restart the timer (using whatever interval was set previously)
myReadTimer->start();
}
Differences from your original approach:
Since you're stopping and restarting the timer, the next time it fires will be interval after your slot function finishes.
Do you need to do anything special at all?
In a single-threaded Qt application, if you're already handling a signal, another signal won't "jump in the middle" of that code. Instead it'll be queued up as an even to handle immediately after the current slot returns.
So perhaps you don't need to stop or disconnect your timer at all.
Differences from your original approach:
If on_btnDownload_clicked takes a while to execute, you might have multiple ReadMyCom events queued up after on_btnDownload_clicked completes. (Note that at this point you'd have an operation that basically "locks up" your GUI for a while anyway; it may make more sense to refactor the function or give it its own thread.)

Controlling a QObject working in another thread, bypassing event queue, freezes the GUI

I'm working with QThread and slots/signals mechanism; I know there's a lot of threads about this on the Web in general and here at SO in particular, but I still could not find a solution. Anyway, here is the context.
The piece of code I am trying to come up with is aimed at controlling though the GUI an eventually long process, hence the use of a QThread.
I have a window with two buttons, start and stop. My Window also has a QThread and Task, where the latter inherits from a QObject. I do want to be able to stop my task while it is running, and to prevent starting it again if start is clicked while it is already running.
Here is an excerpt of Task (which fakes the long process):
class Task: public QObject
{
public:
Task(): QObject(), stop_(true) {}
private slots:
void startTask()
{
stop_ = false;
run();
}
void stopTask()
{
stop_ = true;
}
void run() const
{
while ( ! stop_)
{
sleep(1);
}
}
bool stop_;
};
I made two connections between the buttons and the task in the constructor of my Window:
class Window: public QWidget
{
public:
Window()
{
// Instantiate buttons and put them in a layout.
// ...
connect(buttonStart_, SIGNAL(clicked()), &task_, SLOT(startTask()));
connect(buttonStop_, SIGNAL(clicked()), &task_, SLOT(stopTask()),
Qt::DirectConnection);
task_.moveToThread(&thread);
thread_.start();
}
private:
QPushButton buttonStart_;
QPushButton buttonStop_;
QThread thread_;
Task task_;
};
I used Qt::DirectConnection in the second connect() in order to "force" processing of my signal requesting to stop the task, as (as I understand) task_ needs to return from its work before processing events further (if I use the default connection, all my clicks are processed after my task is "done").
Here, the Qt::DirectConnection "bypasses" the event queue, and that way I can stop my task. But to be honest I don't know if that is the proper way to do it, or if it is a workaround (thus possibly the root of my problem).
Anyway, this works OK that way, but when I start playing with my buttons, the GUI gets eventually frozen, and that's my problem!
Any help is welcome; thanks for your time!
Using a DirectConnection means that the slots will be executed in the UI thread (while your task thread is still running). This is not what you want. The way to handle this is to use an event loop in your thread, by running with QThread::exec().
In order for your thread to be able to respond as you want, you will need to ensure that the thread is able to process incoming events. There are a few ways to deal with this. One would be to call QCoreApplication::processEvents() occasionally while your task is running. Another is to use a QTimer connected to a slot which performs some processing. The important thing is to make sure that the event loop in your thread can run.
The first thing you need to understand is which thread your signal/slot connections are being executed in.
The default behavior in this particular case is to use a Qt::QueuedConnection, which will put your signal event onto the receiving thread's event queue. In the case of a Qt::DirectConnection, the slot is executed in the thread of the object that emitted the signal.
Using a Qt::DirectConnection would only be safe in this instance if you put a mutex around your stop_ variable to prevent both threads from accessing it at the same time.

Can anyone give me same someting to keep in mind while using signals and slots in Qt?

I am learning to program using Qt framework. When I writes some code have signals and slots involved, the events didn't seem to fire and the signals and slots didn't seem to work. It really me make me annoyed. Can you give me some cautions and warnnings about signals and slots in Qt?
slot declarations:
private slots:
void onFtpCmdFinish(int cmdId, bool error);
void onRealtimeFtpCmdsDone(bool error);
connection code:
ftpHandle = new QFtp( this );
connect(ftpHandle, SIGNAL(commandFinished(int, bool)), this, SLOT(onFtpCmdFinish(int, bool)));
connect(ftpHandle, SIGNAL(done(bool)), this, SLOT(onRealtimeFtpCmdsDone(bool)));
Thank you in advance!
In the future, if you ever happen to run into problems with your Qt signals and slots again, the contents of the following blog entry can turn out to be a real life-saver (or at least a very good starting point for your investigations):
http://samdutton.wordpress.com/2008/10/03/debugging-signals-and-slots-in-qt/
It meticulously lists 20 ways to debug/troubleshoot your signals and slots; follow this list and chances are high that you will eventually find out what's wrong.
I hope that helps.
You can only detect failed connect() at runtime.
A couple of tips:
defining QT-FATAL-WARNINGS=1 will cause Qt to assert and quit whenever it gets a connect that doesn't match.
Or wrapping each connect in:
bool ok = connect(……); QASSERT( ok);
Always check the return type, if its true then CONNECT successful else some thing wrong..
Don't forget about the fifth argument Qt::ConnectionType if you will write multithreaded applications

Qt signals & inheritance question

I am relatively new to programming with Qt and had a question. Short version:
How do I inherit signals defined in superclasses?
I am trying to subclass someone else's nicely made QTWidgets to change some of the default behavior:
//Plot3D is a QWidget that defines a signal "rotationChanged"
class matLinePlot : public QObject, public Plot3D {
Q_OBJECT;
//etc...
public:
//etc...
//Catch Plot3D's signal "rotationChanged" and do some magic with it:
void initPlot(){
QObject::connect(this, SIGNAL(rotationChanged( double , double , double )),
this, SLOT(myRotationChanged(double, double, double)));
}
};
The problem is in the QObject::connect line. What I would like to do is connect the rotationChanged SIGNAL (from qwt3D_plot.h) to a local function/SLOT - "myRotationChanged". However whenever I do this, at run time I get:
Object::connect: No such signal matLinePlot::rotationChanged(double, double, double)
in C:...\matrixVisualization.h. Of course, I know that rotationChanged isn't in matrixVisualization.h - it's in qwt_plot3D.h, but I thought that since I inherit from Plot3D everything should be fine. But, now that I think about it, since SIGNAL and SLOT are macros, I assume MOC doesn't know/care about inheritance.
Which leads me to my question - since MOC and SIGNALS / SLOTS don't seem to know about inheritance etc: how can I subclass a widget defined somewhere else and get access to the widget's signals?
I have a lot of examples of how to use encapsulation to accomplish something like this, but I'm afraid I don't understand how to do this with inheritance.
Sorry if this is a ridiculous question - I feel like I'm missing something obvious.
I guess the problem is the multiple inheritance:
class matLinePlot : public QObject, public Plot3D
...
I assume that Plot3D is a subclass of QObject? In this case, you should do
class matLinePlot : public Plot3D
...
instead.
SIGNAL(x) and SLOT(x) are macros that generate string literals. At runtime, slots and signals are matched up using string compares of those generated literals.
(I would have added a comment to mdec's comment, but I don't have enough rep)
I believe that will work if the Plot3D::rotationChanged signal is public or protected. Are you sure the signal is not private?
Edit:
Although I could not find a specific reference, I'll have to conclude that signals are always public. At least a test I did here seemed to indicate that I could connect to a signal even if it was declared in the private section of a class.
I also verified that a signal declared in QObject could be connected using a subclass of QObject in the connect statement so signals are definitely inheritable. As I see in other answers and comments here, the issue must be elsewhere.
Incorrect -> see comments.
I'm using Qtopia at Uni and I believe I recall someone saying something about spacing in the SIGNAL and SLOT parameters for connect.
Try using
QObject::connect(this, SIGNAL(rotationChanged(double,double,double)),
this, SLOT(myRotationChanged(double,double,double)));
I know it doesn't seem intuitive, as C++ isn't sensitive to whitespace, however I believe it has something to do with some of the magic that Qtopia/QT uses when connecting signals and slots. This may only apply to Qtopia, or I may have heard wrong, but give it a try. Additionally are the signals public or protected and have you included the appropriate header files?

Resources