2012-06-05 2 views
2

У меня есть класс X со слотом и класс Y с сигналом. Я настраиваю соединение из класса X и создаю открытый метод в классе Y, чтобы излучать сигнал из класса X (я не уверен, что этот шаг был необходим).Qt сигналы и слоты в разных классах

Затем, если я вызываю этот метод из класса X, выдается сигнал, и слот выполняется. Но если я излучаю сигнал из класса Y, слот никогда не выполняется, и я не понимаю, почему.

Могу ли я установить соединение также в классе Y?

Этот псевдо-код пытается объяснить, что я хочу:

class X : public QWidget { 
    Q_OBJECT 

X(){ 
    connect(Y::getInstance(), SIGNAL(updateSignal(int)), this, SLOT(updateStatus(int))); 
    Y::getInstance().emitSignal(someValue); // Works 
} 

public slots: 
    void updateStatus(int value); 

} 

class Y : public QObject { 

Q_OBJECT 

Y(){ 

} 

public: 
    Y getInstance(); 
    void emitSignal(int value) { 
     emit updateSignal(value); 
    } 


signal: 
    void updateSignal(int value); 
} 

class Z : public Y { 
Z(){ 

} 

init(){ 
emitSignal(someValue); // Doesn't work 
} 
} 
+1

Вы можете указать код? я не могу точно понять, что вы пытаетесь сказать – alegen

+0

Нет, вам нужно установить соединение только один раз. Пожалуйста, разместите часть своего кода. – Ammar

+0

Это очень сложный код, поэтому я напишу немного псевдо, чтобы лучше объяснить вопрос. –

ответ

4

Помните, что соединения не между классов, но между экземплярами. Если вы излучаете сигнал и ожидаете, что подключенные слоты должны быть вызваны, он должен быть испущен на экземпляре, на котором было произведено соединение. Это твоя проблема.

Предполагая, что Y является Singleton:

Если вы connect(Y::getInstance(), ...)

и Y::getInstance() делает new Y() в какой-то момент, то конструктор Y называется перед тем соединение устанавливается вверх. Таким образом, сигнал будет излучаться, но слот еще не прослушает его.

Кроме того, было бы лучше, чтобы сделать одну из следующих вещей, но вы не могли бы излучать сигнал в конструкторе Y с этими подходами:

  • Используйте третий класс Z, который знает, как X и Y, и сделайте соединение там
  • Инъекция зависимостей. Это означает, что Х получает экземпляр Y в его конструктор:

Пример для инъекций Конструктор зависимостей:

X::X(Y* const otherClass) 
{ 
    connect(otherClass, SIGNAL(...), this, SLOT(...) 
} 
0

Вы излучающий сигнал из конструктора. В то время Y::getInstance() не имеет смысла В СООТВЕТСТВИИ С ЭТОГО фрагментом кода.

+0

Это просто упрощение , Я действительно получаю Y-образ. Если нет, я бы не сказал, что emitSignal работает с X –

+0

Да. вы вызываете 'Y :: getInstance(). emitSignal (someValue);' из X. Он работает, потому что в то время у вас есть объект Y. Но вы не можете сделать это из конструктора Y. – shan

+0

Хорошо, это не происходит у конструктора, это происходит в другой части кода Y. Во всяком случае, я не понимаю, почему я не могу назвать метод Y из конструктора Y. –

1

Его простой. См. Ниже пример.

Если вы хотите записать сигналы & слотов в вашем собственном классе, вы должны отвечать двум условиям ...

1. Your class must inherit from QObject class or any class derived from QObject. 

2. The Q_OBJECT macro must appear in a private section in your class.

/* Sender.h */ 

#ifndef SENDER_H 
#define SENDER_H 

#include <QObject> 

class Sender : public QObject 
{ 
    Q_OBJECT 
public: 
    explicit Sender(QObject *parent = 0);  
    void fireSignal(); 

signals: 
    void foo(const QString& arg); 
}; 

#endif // SENDER_H 


/* Sender.cpp*/ 


#include "Sender.h" 

Sender::Sender(QObject *parent) : 
    QObject(parent) 
{ 
} 


void Sender::fireSignal() 
{ 
    emit foo("This a message sender is sending to receiver."); 
} 
код

Сейчас в ресивере ниже

/* Receiver.h */ 

#ifndef RECEIVER_H 
#define RECEIVER_H 

#include <QObject> 

class Receiver : public QObject 
{ 
    Q_OBJECT 
public: 
    explicit Receiver(QObject *parent = 0); 

public slots: 
    void bar(const QString& arg); 

}; 

#endif // RECEIVER_H 

/* Receiver.cpp */ 

#include "Receiver.h" 
#include <iostream> 

Receiver::Receiver(QObject *parent) : 
    QObject(parent) 
{ 
} 


void Receiver::bar(const QString &arg) 
{ 
    std::cout << arg.toStdString(); 
} 

Теперь main.cpp код

#include <QtCore/QCoreApplication> 
#include "Sender.h" 
#include "Receiver.h" 

int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 

    Sender sender; 
    Receiver receiver; 

    QObject::connect(&sender, SIGNAL(foo(QString)), &receiver, SLOT(bar(QString))); 

    sender.fireSignal(); 

    return a.exec(); 
} 

Вот так.

Наконец, если вы хотите использовать другой синтаксис для метода подключения. Пожалуйста, используйте приведенные ниже строки.

QObject::connect(&sender,&Sender::foo,&receiver,&Receiver::bar); 

Надеюсь, это вам помогло. Спасибо

Смежные вопросы