質問

I've recently started using Qt and I need some clarification on signal/slot mechanism. I understand how it's a great tool for the GUI and communication between objects living in separate threads, but I'm not quite sure whether I should use it in a simple cases like the following one.

I have three classes, let's call them MainWindow, DataManager and DataWorker. DataWorker lives in a separate thread and signals when new data is ready for collection. It is then visualised in MainWindow widgets after some processing. I've created DataManager class as to not pollute the GUI class with processing code.

Now, how should I handle the communication between DataManager and the MainWindow.


Option #1 - have a pointer to MainWindow as a member and just call its method

class MainWindow
{
private:
    DataManager* dm;

public:
    MainWindow() : dm(new DataManager(this)) { }
    displayData(const char* processedData);
}

class DataManager : QObject
{
private:
    MainWindow *mw;

private slots;
    eventNewData()
    {
        // get and process the data
        mw = this->QObject.parent();
        mw->displayData(const char* processedData);
        // release data
    }
}

Option #2 - signal new data to call MainWindow slot

class MainWindow
{
private:
    DataManager* dm;

private slots:
    displayData(const char* processedData);

public:
    MainWindow() : dm(new DataManager(this)) { QObject::connect(dm, SIGNAL(newData(const char*)), this, SLOT(displayData(const char*)); }

};

class DataManager : QObject
{    
signals:
    newData(const char* processedData);

private slots;
    eventNewData()
    {
        // get and process the data
        emit newData(processedData);
        // release data
    }
}

Option 1 seems more intuitive to me, but then again I don't know Qt very well. I can see the benefit of using signals and slots if there will be more classes that I'd like to react to a newData() signal.

So what's a better option and is there any difference in performance between the two?

役に立ちましたか?

解決

The first option does provide better performance than using the signal/slot mechanism, but it also has the drawback that there is a tight coupling between MainWindow and DataManager. Both know each other, so they can't really be used separately. That alone should already be a reason to refactor the code.

That said, as a third option you could let MainWindow have the slot that received the signal from DataWorker and let DataManager be a helper class that just converts the data into a usable format for MainWindow.

class MainWindow
{
private:
    DataManager* dm;

public:
    MainWindow() : dm(new DataManager()) { }
    displayData(QString processedData);
private slots;
    eventNewData()
    {
        // get the data
        QString processedData = dm->preprocessData(data);
        displayData(processedData);
        // release data
    }
};

class DataManager
{
public:
    QString preprocessData(...);
};

他のヒント

You cannot call GUI functions directly from your thread. So option #1 won't work, unless there's a signal/slot connection between DataWorker and DataManager::eventNewData(). The only way to call GUI functions from another thread is through a signal/slot connection.

Signal/slot communication always incurs overhead, since it's purely runtime-based and operates on strings (the names of the slots are generated at compile time, and then compared at runtime.) It's dynamic dispatch. Direct function calls are always faster.

So the answer is simple: if you don't need a signal, don't use one. In this particular case, it doesn't look like you need it for communication between DataManager and MainWindow, since all you want is call MainWindow::displayData(). It doesn't look like you would ever need to change that dynamically and call a different function. Signals and slots are there to provide inter-thread communication and switchboard-like connections. If you don't need either, then there's no need to use signals.

I don't know exactly how QT works so I'm not sure if there is a performance hit but my intuition says 1. there shouldn't be a big difference 2. it will probably not matter anyway in a GUI context.

The option using the standard QT mechanism has the benefit of the DataManager not needing to know anything about the GUI. Many people consider this good design because it can allow you to replace your GUI without changes to the internals.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top