3

我最近开始使用 Qt,我需要对信号/插槽机制进行一些说明。我了解它是一个很好的工具,用于 GUI 和生活在不同线程中的对象之间的通信,但我不太确定是否应该在像下面这样的简单情况下使用它。

我有三个类,我们称它们为 MainWindow、DataManager 和 DataWorker。DataWorker 位于一个单独的线程中,并在新数据准备好收集时发出信号。然后在经过一些处理后在 MainWindow 小部件中可视化。我创建了 DataManager 类,以免用处理代码污染 GUI 类。

现在,我应该如何处理 DataManager 和 MainWindow 之间的通信。


选项#1 - 有一个指向 MainWindow 作为成员的指针,只需调用它的方法

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
    }
}

选项 #2 - 发出新数据以调用 MainWindow 插槽

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
    }
}

选项 1 对我来说似乎更直观,但话又说回来,我不太了解 Qt。如果有更多类我想对 newData() 信号做出反应,我可以看到使用信号和插槽的好处。

那么有什么更好的选择,两者之间的性能有什么区别吗?

4

3 回答 3

3

您不能直接从您的线程调用 GUI 函数。所以选项 #1 将不起作用,除非 DataWorker 和 DataManager::eventNewData() 之间存在信号/插槽连接。从另一个线程调用 GUI 函数的唯一方法是通过信号/插槽连接。

信号/槽通信总是会产生开销,因为它纯粹基于运行时并且对字符串进行操作(槽的名称在编译时生成,然后在运行时进行比较。)它是动态调度。直接函数调用总是更快。

所以答案很简单:如果你不需要信号,就不要使用。在这种特殊情况下,DataManager 和 MainWindow 之间的通信似乎不需要它,因为您只需要调用 MainWindow::displayData()。看起来您不需要动态更改它并调用不同的函数。信号和插槽用于提供线程间通信和类似交换机的连接。如果您都不需要,则无需使用信号。

于 2012-11-13T14:38:32.333 回答
3

第一个选项确实提供了比使用信号/槽机制更好的性能,但它也有一个缺点,即MainWindow 和之间存在紧密耦合DataManager。两者都互相认识,所以它们不能真正分开使用。仅此一项就应该是重构代码的理由。

也就是说,作为第三种选择,您可以让接收MainWindow信号的插槽成为一个帮助类,它只是将数据转换为.DataWorkerDataManagerMainWindow

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(...);
};
于 2012-11-13T15:33:34.043 回答
0

我不确切知道 QT 是如何工作的,所以我不确定是否会影响性能,但我的直觉说 1. 应该没有太大的区别 2. 在 GUI 上下文中可能无论如何都无关紧要。

使用标准 QT 机制的选项的好处是 DataManager 不需要了解有关 GUI 的任何信息。许多人认为这是一个很好的设计,因为它可以让您在不更改内部结构的情况下替换您的 GUI。

于 2012-11-13T14:50:02.633 回答