Сигнал Qt в слот конкретного объекта - PullRequest
3 голосов
/ 20 июля 2009

Я хотел бы знать, какой из следующих способов является правильным способом работы с сигналом / слотом в Qt.

Мне нужен способ иметь несколько экземпляров диалога, т. Е. A и B. И мне нужно сказать 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");

это правильно?

Спасибо!

Ответы [ 2 ]

2 голосов
/ 14 апреля 2014

Поскольку ваш слот находится в другом потоке, вы должны использовать мета-объектную систему для асинхронного вызова метода. Правильный способ сделать это - использовать QMetaObject::invokeMethod

НЕ наследовать QThread и не переопределять метод run. Подробнее об этом см .: http://blog.qt.digia.com/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");
1 голос
/ 20 июля 2009

В этом упрощенном примере, я думаю, вы находитесь на правильном пути с опцией 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, чтобы иметь возможность вести журнал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...