3

我想知道以下哪一项是在 Qt 中处理信号/插槽的正确方法。

我需要一种方法来拥有 Dialog 的多个实例,即:AB. 我需要告诉A打印“A”并B从不同的线程打印“B”。所以我相信我需要类似的东西:

选项 1) A->print("A")B->print("B")

还是这样做更好:

选项 2) emit print("A")并且emit print("B")使用我不知道的方式,所以只A抓住“A”,只B抓住“B”。

我的选项 1 是这样工作的:

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

然后我要做的就是:

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

这是正确的吗?

谢谢!

4

2 回答 2

2

由于您的插槽在另一个线程中,因此您必须使用元对象系统来异步调用该方法。正确的方法是使用QMetaObject::invokeMethod

不要继承 QThread 并覆盖 run 方法。有关这方面的详细信息,请参阅:https ://www.qt.io/blog/2010/06/17/youre-doing-it-wrong

void otherClass::printTo(myClass* instance, char* text)
{
    QMetaObject::invokeMethod(instance,        // pointer to a QObject
                              "doPrint",       // member name (no parameters here)
                              Qt::QueuedConnection,     // connection type
                              Q_ARG(char*, text));     // parameters
}

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

myClass* instanceA = new myClass();
myClass* instanceB = new myClass();
printTo(instanceA, "A");
printTo(instanceB, "B");

如果 char* 类型尚未在元对象系统中注册,请使用 Q_DECLARE_METATYPE(char*);

然后:

qRegisterMetaType<char*>("charPtr");
于 2014-04-13T22:07:23.983 回答
1

在这个简化的示例中,我认为您在选项 1 的正确路径上。但是,如果您不需要该doPrint()方法会更好,这也将消除对mySignal信号的需要(至少在 中myClass)。相反,我建议从QThread尚未继承的线程中继承你的线程,并执行以下操作:

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

然后你需要做这样的事情:

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

显然,在大多数非示例代码中,您不会将字符串传递给 run,而是生成要在运行时运行的字符串threadA。好处是这样可以避免线程考虑myClass,您只需要考虑它们连接的位置。另一方面,您在线程中引入的依赖项更少,因为它们不需要知道myClass能够记录。

于 2009-07-20T18:59:25.607 回答