views:

884

answers:

1

Hello,

I would like to know which of the following is the proper way of doing thing with signal/slot in QT.

I need a way to have multiple instance of a Dialog, i.e: A and B. And I need to tell A to print "A" and B to print "B" from a different thread. So I believe I need something like either:

OPTION 1) A->print("A"); and B->print("B")

or is it better to do:

OPTION 2) emit print("A") and emit print("B") and use a way that I don't know so only A catch the "A" and only B catch the "B".

I got the option 1 working like this:

class myClass : public QMainWindow
{
    Q_OBJECT

public:
    myClass (QWidget *parent = 0, Qt::WFlags flags = 0);
    ~myClass ();
    void doPrint(char* text)
    {
         emit mySignal(text);
    }
private:
    Ui::myClass ui;

public slots:
    void newLog(char* msg);

signals:
     void mySignal(char* msg);
};

myClass::myClass(QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags)
{
    ui.setupUi(this);
    connect(this, SIGNAL(mySignal(char*)), this, SLOT(newLog(char*)));
}

void myClass::newLog(char* msg)
{
    ui.textEdit->append(msg);
}

and then All i have to do is:

myClass* instanceA = new myClass();
myClass* instanceB = new myClass();
instanceA->doPrint("A");
instanceB->doPrint("B");

is this right?

Thanks!

A: 

In this simplified example, I think you are on the correct path with option 1. However, it would be even better if you didn't need the doPrint() method, which would also eliminate the need for the mySignal signal (at least in myClass). Instead, I would suggest inheriting your threads from QThread if the aren't already, and doing something like this:

class myThread : public QThread
{
    Q_OBJECT

public:
    myThread (QWidget *parent = 0 ) : QThread(parent) {}
    ~myThread () {}
    void run(char* text)
    {
         emit mySignal(text);
    }

signals:
     void mySignal(char* msg);
};

Then you need to do something like this:

myClass* instanceA = new myClass();
myThread* threadA = new myThread();
connect(threadA, SIGNAL(mySignal(char*)), instanceA, SLOT(newLog(char*)), Qt::QueuedConnection);
threadA->run( "A" );

Obviously, in most non-example code, you'd not pass the string into run, but rather generate strings to be run as threadA is running. The advantage is that this keeps the thread considerations out of myClass, and you only need to think about them where they are connected. On the flip side, you introduce fewer dependencies into the threads, since they don't need to know about myClass to be able to log.

Caleb Huitt - cjhuitt
Please stop spreading this misinformation about Qt::QueuedConnection being required in this case. It isn't anymore, for the last three Qt versions.
@mmutz, I did that in my example to ensure the type of connection, based on http://doc.trolltech.com/4.5/threads.html#signals-and-slots-across-threads which states in part "QThread objects live in the thread where the object was created -- not in the thread that is created when QThread::run() is called. It is generally unsafe to provide slots in your QThread subclass." However, I now see that "you can safely emit signals from your QThread::run() implementation...", which I had previously missed. Regardless, specifying the connection type does not harm anything that I can see.
Caleb Huitt - cjhuitt