2010-03-04 39 views
9

Arka plan iş parçacığım var ve iş parçacığı UI'yi güncelleyen bazı yöntemleri çağırıyor (ilerleme çubuklarını göstermek ve metin alanlarında ek bilgi göstermek için).Qt: Arka plan iş parçacığı yenileme UI iş parçacığı

Bazı UI widget değerlerini değiştirirseniz, "Farklı bir iş parçacığının sahip olduğu nesnelere olay gönderilemiyor" onaylama hatası ortaya çıkar.

Forumlara baktığımda, QMetaObject :: invokeMethod yöntemini kullanabileceğimi okudum, ancak yalnızca yukarıda gösterilen aynı hatayı artıran Qt :: DirectConnection bayrağını iletirsem çalışır.

Qt :: QueuedConnection veya Qt :: AutoConnection kullanırsam, invokeMethod false değerini döndürür.

Benim kod şuna benzer:

.h:

class A : public QMainWindow 
{ 
    Q_OBJECT 

    QProgressBar* pb; 

    public slots: 
    bool m(bool, int); 
}; 

class B 
{ 
    A* a; 

    public: 
    void handleEvent(); 
}; 


.cpp: 

bool A::m(bool x, int y) 
{ 
    pb->setValue(y); 
    return x; 
} 

void B::handleEvent() 
{ 
    //a->m(true, 12); //raises an assertion error 

    bool r; 
    //bool ret = QMetaObject::invokeMethod(a, "m", Qt::DirectConnection, Q_RETURN_ARG(bool, r), Q_ARG(bool, true), Q_ARG(int, 12)); //raises the same assertion error error 

    bool ret = QMetaObject::invokeMethod(a, "m", Qt::AutoConnection, Q_RETURN_ARG(bool, r), Q_ARG(bool, true), Q_ARG(int, 12)); //is ignored and ret contains false. 
} 

sen neler olduğunu ya da ben yanlış yapıyorum biliyor musunuz? ya da belki, birisi benim yeni sorunumla başa çıkmak için başka bir yaklaşım önerebilir mi? peşin

sayesinde

Ernesto

cevap

10

ben invokeMethod() kendim kullanmadıysanız, ama bunu yapmak için, genellikle sadece sinyalleri ve yuvaları kullanın. Örneğin, ilerleme günceller class A yuvaya bağlanır class B üyesi olarak bir sinyal oluşturabilir:

class B : public QObject 
{ 
    Q_OBJECT 

    A* a; 

signals: 
    void update_signal(bool, int); 

public: 
    void handleEvent(); 
}; 

B::B() 
{ 
    //assuming a already points to the correct place... 
    connect(this, SIGNAL(update_signal(bool,int), 
      a, SLOT(m(bool,int)), Qt::QueuedConnection); 
} 

void B::handleEvent() 
{ 
    emit update_signal(true, 12); 
} 

A::m() bu durumda boşluğu geri dönmek zorunda kalacak ne var ki bir sorun değildir kuyruğa alınmış bir bağlantı kullanarak, çağrı senkronize olmadığından (emit update_signal(true,12) yuva işlevi çağrılmadan önce bir dönüş değeri elde etmek imkansız hale getirilmeden geri dönebilir) bir dönüş değeri alamazsınız.

Bu bağlantıyı, A türünde bir nesneye ve B türünde bir nesneye işaretçiniz olduğu sürece bu bağlantıyı gerçekleştirebilirsiniz. Bu, sinyalleri ve yuvaları çok esnek hale getirir, çünkü B'dan A'u tamamen çözebilirsiniz, ancak yine de bunların sinyaller ve yuvalarla iletişim kurmasına izin verin. Örneğin:

class B : public QObject 
{ 
    Q_OBJECT 

signals: 
    void update_signal(bool, int); 

public: 
    void handleEvent(); 
}; 

void B::handleEvent() 
{ 
    emit update_signal(true, 12); 
} 

class A : public QMainWindow 
{ 
    Q_OBJECT 

    QProgressBar* pb; 

    public slots: 
     void m(bool, int); 
}; 

void A::m(bool x, int y) 
{ 
    pb->setValue(y); 
} 

int main() 
{ 
    A* a = new A(); 
    B* b = new B(); 

    QObject::connect(b, SIGNAL(update_signal(bool, int)), 
      a, SLOT(m(bool, int)), Qt::QueuedConnection); 

    //... 
} 

Bu durumda, b bir işaretçi saklamak veya a hakkında hiçbir şey bilmek zorunda değildir ama onlar ince iyi tanımlanmış kanal aracılığıyla iletişim kurabilir.

İlgili konular