Originally Posted by
manucorrales
Can you explain to me a little more the queue and slot and signals approach?
Sure. It's quite easy:
class PrinterThread
: public QThread{
Q_OBJECT
public:
...
public slots:
void foo( const QString& str );
signals:
void bar();
...
};
void PrinterThread::run()
{
exec(); // <- this is very important
}
void PrinterThread::foo( const QString& str )
{
...
emit bar();
...
}
...
connect( someObject, SIGNAL( someSignal( const QString& ) ), printerThread, SLOT( foo( const QString& ) ), Qt::QueuedConnection );
connect( printerThread, SIGNAL( bar() ), someObject, SLOT( barReceiver() ), Qt::QueuedConnection );
...
class PrinterThread : public QThread
{
Q_OBJECT
public:
...
public slots:
void foo( const QString& str );
signals:
void bar();
...
};
void PrinterThread::run()
{
exec(); // <- this is very important
}
void PrinterThread::foo( const QString& str )
{
...
emit bar();
...
}
...
connect( someObject, SIGNAL( someSignal( const QString& ) ), printerThread, SLOT( foo( const QString& ) ), Qt::QueuedConnection );
connect( printerThread, SIGNAL( bar() ), someObject, SLOT( barReceiver() ), Qt::QueuedConnection );
...
To copy to clipboard, switch view to plain text mode
As you can see you don't need much to get it work.
When you invoke foo() slot through a queued connection (i.e. using a signal --- don't even try to invoke it directly), Qt will create a QEvent object, copy all parameters and post that event to the PrinterThread event loop. Later PrinterThread will pick that event, invoke the foo() slot and return back to the event loop to wait for another event --- and that's all.
If you want to subclass QThread (as in the above example), make sure that you use queued connections (direct and automatic connections won't work).
Also you can try to do it like this:
// implements the communication protocol
// only PrinterThread should use it
class PrinterController
: public QObject{
Q_OBJECT
public:
...
public slots:
void doSomething();
signals:
void done();
...
};
// provides printer interface to the rest of the application
class PrinterThread
: public QThread{
Q_OBJECT
public:
...
signals:
void done();
void doSomething();
}
void PrinterThread::run()
{
PrinterController controller;
connect( this, SIGNAL( doSometing() ), &controller, SLOT( doSomething() ) );
connect( &controller, SIGNAL( done() ), this, SIGNAL( done() ) );
exec();
}
...
connect( printerThread, SIGNAL( done() ), someObject, SLOT( continueWork() ) );
printerThread->doSomething(); // this behaves just as a non-blocking call
...
// implements the communication protocol
// only PrinterThread should use it
class PrinterController : public QObject
{
Q_OBJECT
public:
...
public slots:
void doSomething();
signals:
void done();
...
};
// provides printer interface to the rest of the application
class PrinterThread : public QThread
{
Q_OBJECT
public:
...
signals:
void done();
void doSomething();
}
void PrinterThread::run()
{
PrinterController controller;
connect( this, SIGNAL( doSometing() ), &controller, SLOT( doSomething() ) );
connect( &controller, SIGNAL( done() ), this, SIGNAL( done() ) );
exec();
}
...
connect( printerThread, SIGNAL( done() ), someObject, SLOT( continueWork() ) );
printerThread->doSomething(); // this behaves just as a non-blocking call
...
To copy to clipboard, switch view to plain text mode
With this approach you don't have to remember about adding Qt::QueuedConnection and you get a non-blocking interface to your printer.
Just remember that Qt will copy all parameters, even if you use const references. If it complains that you can't send SomeCustomType through queued connection, then it means that you have to register that type first with qRegisterMetaType() (search the forum for more info about this).
Bookmarks