Russian Qt Forum

Qt => Общие вопросы => Тема начата: Impuls от Январь 14, 2011, 01:01



Название: Первый вызов сигнала
Отправлено: Impuls от Январь 14, 2011, 01:01
Доброго времени суток уважаемые эксперты. Для начала хочу извиниться за туманную формулировку названия темы.
Сразу перейду к делу:
Есть класс А, в нем пара: Сигнал->Слот. Эта пара занимается синхронизацией двух объектов, причем объекты являются полями другого класса:
Класс B включает объекты класса А.
При изменении объекта а1, должна произойти некоторая модификация объекта а2, и наоборот. Причем никто не ограничивает количество таких объектов.
А теперь проблема: Сразу после создания (еще до соединения двух объектов), объекты рассинхронизированы и не могут быть сведены в единое целое без сигнала из вне. После соединения, и модификации одного из объектов - происходит синхронизация. А вот меня интересует граничный случай: объекты созданы, соединены, но не модифицированы. Как можно провести их синхронизацию после соединения? Надеюсь вразумительно смог объяснить ситуацию)).
Приведу пример. Он, конечно, надуманный, но суть проблемы отражает:
Код:
class A : QObject
{
Q_OBJECT
public:
void Print();
        A(){
                a1 = rand();};
ModifiA1(int _a1){
a1 = _a1;
emit SignalS(a1);};
signal:
SignalS(int Data);
public slots:
SlotS(int Data){
a2 = Data;};
private:
int a1,a2;
};

class B : QObject
{
Q_OBJECT
public:
B(){
a1 = new A;
a2 = new A;
connect(a1, SIGNAL(SignalS(int)), a2, SLOT(SlotS(int));
connect(a2, SIGNAL(SignalS(int)), a1, SLOT(SlotS(int));};
ModifiA1(int a){
a1.ModifiA1(a);
}
ModifiA2(int a){
a2.ModifiA1(a);
}
private:
A *a1,*a2;
}
Понятно, что после вызова методов ModifiA1 и ModifiA2 - объекты синхронизируются, но до этого объекты не будут дружить друг с дружкой(((
Заранее спасибо.


Название: Re: Первый вызов сигнала
Отправлено: GreatSnake от Январь 14, 2011, 09:22
см. QMetaObject::invokeMethod()


Название: Re: Первый вызов сигнала
Отправлено: Impuls от Январь 14, 2011, 13:15
см. QMetaObject::invokeMethod()
Если я правильно понял QMetaObject::invokeMethod() - вызывает любой сигнал или слот. Но в любом случае мне нужно будет сделать такую конструкцию:
connect()
QMetaObject::invokeMethod()
А я же хотел чтобы сразу после connect автоматически вызывался сигнал, чтобы я дальше не заботился о синхронизации. Такое вообще реально?


Название: Re: Первый вызов сигнала
Отправлено: andrew.k от Январь 14, 2011, 14:18
зачем invokeMethod? invokeMethod синхронизирует объекты позже (асинхронно), когда будет запущен евент луп либо когда подойдет очередь события. Поэтому какое-то время объекты будут не синхронизированы.
Такое решение не всегда будет подходить задаче.
Поэтому сразу после коннекта вызови слот напрямую. И все. Что может быть проще?


Название: Re: Первый вызов сигнала
Отправлено: GreatSnake от Январь 14, 2011, 14:23
Цитата: andrew.k
invokeMethod синхронизирует объекты позже (асинхронно)
Цитировать
The invocation can be either synchronous or asynchronous, depending on type:
If type is Qt::DirectConnection, the member will be invoked immediately.
If type is Qt::QueuedConnection, a QEvent will be sent and the member is invoked as soon as the application enters the main event loop.
If type is Qt::BlockingQueuedConnection, the method will be invoked in the same way as for Qt::QueuedConnection, except that the current thread will block until the event is delivered. Using this connection type to communicate between objects in the same thread will lead to deadlocks.
If type is Qt::AutoConnection, the member is invoked synchronously if obj lives in the same thread as the caller; otherwise it will invoke the member asynchronously.


Название: Re: Первый вызов сигнала
Отправлено: Impuls от Январь 14, 2011, 15:09
Поэтому сразу после коннекта вызови слот напрямую. И все. Что может быть проще?
Все легко. Однако это все лишние телодвижения, про которые можно легко забыть. А это чревато последствиями. Так что лучше: сделать класс и забыть про его реализацию, или все равно забыть про реализацию, а потом натыкаться на таких мелких гаденышей?


Название: Re: Первый вызов сигнала
Отправлено: Impuls от Январь 14, 2011, 17:11
Проблема решена QObject::connectNotify - вызывается всякий раз, когда происходит соединение сигналов класса
Вот пример:
Код:
#ifndef QTESTCLASS_H
#define QTESTCLASS_H

#include <QObject>

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

    void CallSignl(int a);
protected:
    virtual void connectNotify(const char *signal);
signals:
    void TestSignal(int a);
public slots:
    void TestSlot(int a);
};

#endif // QTESTCLASS_H
Код:
#include "QTestClass.h"
#include <iostream>
#include <QLatin1String>

using namespace std;

QTestClass::QTestClass(QObject *parent) : QObject(parent)
{
}
void QTestClass::CallSignl(int a)
{
    emit TestSignal(a);
}
void QTestClass::connectNotify(const char *signal)
{
     if (QLatin1String(signal) == SIGNAL(TestSignal(int))) {
        cout<<"Сигнал был соединен со слотом"<<endl;
     }
}

void QTestClass::TestSlot(int a)
{
    cout<<a<<endl;
}
Код:
#include <QApplication>
#include <QObject>
#include "QTestClass.h"


int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    QTestClass *a = new QTestClass;

    QObject::connect(a, SIGNAL(TestSignal(int)), a, SLOT(TestSlot(int)));
    a->CallSignl(10);
    QObject::connect(a, SIGNAL(TestSignal(int)), a, SLOT(TestSlot(int)));
    a->CallSignl(15);
    return app.exec();
}


Название: Re: Первый вызов сигнала
Отправлено: andrew.k от Январь 15, 2011, 16:48
Цитата: andrew.k
invokeMethod синхронизирует объекты позже (асинхронно)
Цитировать
The invocation can be either synchronous or asynchronous, depending on type:
If type is Qt::DirectConnection, the member will be invoked immediately.
If type is Qt::QueuedConnection, a QEvent will be sent and the member is invoked as soon as the application enters the main event loop.
If type is Qt::BlockingQueuedConnection, the method will be invoked in the same way as for Qt::QueuedConnection, except that the current thread will block until the event is delivered. Using this connection type to communicate between objects in the same thread will lead to deadlocks.
If type is Qt::AutoConnection, the member is invoked synchronously if obj lives in the same thread as the caller; otherwise it will invoke the member asynchronously.
Точно, я забыл об этом. только что занимался многопоточкой и там использовал invokeMethod поэтому привык :)