ã©ãããããããVS2009ã®WinXPã®Qt 5.1.1ã§éäžçãªä¿¡å·äº€æãè¡ããã«ãã¹ã¬ããã¢ããªã±ãŒã·ã§ã³ãå®è£ ããå¿ èŠããããŸããã ç§ã¯SchleeãåããQThreadããã¯ã©ã¹ãç¶æ¿ããå¿ èŠãããããšã圌ããå·®ãåŒããŸããã 念ã®ããã Qtã®ããã¥ã¡ã³ãã調ã¹ãŸãããã¯ã©ã¹ãç¶æ¿ããQThreadã«å察ãã人ã¯ããŸããã§ããã ããŠ-泚æã¯å®äºã§ãïŒ ç§ã¯ãããå§ããŸã-ããã¯ããŸãããããã§ãããã©ããããããããã§ã¯ãããŸãã...ç§ã¯ãããã°ã¢ãŒãã§è¿œè·¡ãå§ããŸã-ãããŠæªéã¯ããã§äœãèµ·ãã£ãŠããã®ãç¥ã£ãŠããŸãïŒ ã·ã°ãã«ãçµäºããã«çµäºããåŸãäœããã®çç±ã§æ²ãã£ãŠå¥ã®ã¹ããªãŒã ããåºãŸãã äžèšã§èšãã°ãå®å šãªæ··ä¹±ïŒ ç§ã¯åŸ¹åºçã«ã°ãŒã°ã«ã§èª¿ã¹ãŠããããã¯ãç解ããªããã°ãªããŸããã§ããïŒ ããã®èšäºã ãã ããããŠããã®èšäºãç§ãå©ããŠãããŸããïŒã ãã®çµæãC ++ïŒãŸãã¯ãããã®éå±€å šäœïŒã§ã¯ã©ã¹ãã³ãã¬ãŒããäœæããŸãããããã«ãããæ£ããå®å®ããŠåäœããå¥ã®ã¹ã¬ããã«ååšããã¯ã©ã¹ã®ïŒæ¯èŒçïŒå°ããªã³ãŒããèšè¿°ã§ããŸããã
UpdïŒ ã³ã¡ã³ãã§åœŒãã¯ããè¯ãã¢ãããŒããææ¡ããŸãã-ç§ã¯ãããæ°ããèšäºã§èª¬æããŸãã ã
äœã欲ãã
ç§ã¯éåžžã«æçœãªããšãæ±ããŠåªåããŸããïŒ
- ãã¹ãŠã®æ å ã®äžã§C ++ã¯ã©ã¹ã䜿çšããŸããã€ãŸããã¹ããªãŒã ã®äœææã«ã³ã³ã¹ãã©ã¯ã¿ãŒãåŒã³åºãããç Žæ£åã«ãã¹ãã©ã¯ã¿ãåŒã³åºãããŸãã
- ãã¹ãŠã®æ å ã§Qtã®æ©èœã䜿çšããŸã-ããªãã¡ãä¿¡å·ã¹ãããæ¥ç¶ãã€ãã³ããªã©ã
- å¿ èŠã«å¿ããŠ-äœæãšäœæ¥ã®ããã»ã¹ãå¶åŸ¡-ãããŒã®åªå é äœãäœæ¥ã®éå§ã«é¢ããã¹ããããç·æ¥å®äºã«é¢ããä¿¡å·ã
- æå°éã®èœæžããšæ倧éã®æçãã
ç§ã¯æ¬¡ã®ãããªãã®ãåŸãŸããïŒ
class SomeJob: public QObject { Q_OBJECT public: SomeJob () { /* ... */ } // ~SomeJob () { /* ... */ } // signals: void finished (); // public slots: void to_terminate () { /* ... */ } // }; ... ThreadedObject<SomeJob> thr; // - thr.start (); //
çŸäººïŒ
ã©ã®ããã«è¡åããã
Qt 5.1ã§ã¯ãäœã¬ãã«ã®QThreadã¯ã©ã¹ã¯ç§ãã¡ã®ç®çã®ããã®ãã®ã§ãã 圌ã«ã€ããŠæ¬¡ã®ããã«èšãããŠããŸãïŒãQThreadã¯ã©ã¹ã¯ããã©ãããã©ãŒã ã«äŸåããªãæ¹æ³ã§ã¹ã¬ããã管çããæ©èœãæäŸããŸããã Schleeã«ã¯çŽ æŽãããæ¬ããããŸãããããã«éåžžã«çŽããããã¹ã¬ããã®äŸããããŸããQThreadã¯ã©ã¹ãç¶æ¿ããrunïŒïŒã¡ãœããããªãŒããŒã©ã€ããããã®äžã§äœæ¥ãè¡ãããšããå§ãããŸãã ããã¯ããéå§ãæ©èœã®å®è¡ãå®äºãã®ã¹ã¿ã€ã«ã®ã¿ã¹ã¯ã«ã¯æªãããšã§ã¯ãããŸããããããè€éãªã±ãŒã¹ã§ã¯æ確ã«åãå ¥ããããŸããã
äžè¬çã«ãç§
ãããã£ãŠãæåã®è¿äŒŒã§ã¯ãåé¡ã®è§£æ±ºçã¯æ¬¡ã®ãšããã§ãã
- ã¹ã¬ããäœæ-QThreadã¯ã©ã¹ã
- ãªããžã§ã¯ããäœæãããããæ°ããã¹ããªãŒã ã«è»¢éããŸãã
- ä¿¡å·ã¹ãããéä¿¡ã®èšçœ®ã
- ç¹å®ã®åªå 床ã§ã¹ããªãŒã ãéå§ããŸãã
ãã¹ãŠããŸãããããã§ãããèŠããŠããŸããïŒ -äœæããããªããžã§ã¯ãã®ã³ã³ã¹ãã©ã¯ã¿ãŒãæ°ããã¹ã¬ããã§å®è¡ãããã ãããè¡ãã«ã¯ãã¹ã¬ããã®éå§åŸã«éå§ããå¿ èŠããããŸãã æåã«ãªããžã§ã¯ããäœæãã次ã«ã¹ããªãŒã ãäœæã§ããŸãã ãã ãããªããžã§ã¯ãã®ã³ã³ã¹ãã©ã¯ã¿ãŒã«ãã£ãŠäœæããããã¹ãŠã®ãã®ã¯ãæ°ããã¹ã¬ããã§ã¯ãªãã çŸåšã®ã¹ã¬ããã®ã¹ã¿ãã¯ïŒããŒãïŒã«é 眮ãããŸãã ãã®ãšã³ãããŒã®ãã¹ãŠãæ°ããã¹ã¬ããã«ããŸã転éããå€ãã¹ã¬ããã§åé€ããããšã¯ã§ããŸããã...æ°ããã¹ã¬ããã§æ¢ã«ã³ã³ã¹ãã©ã¯ã¿ãŒãåŒã³åºãæ¹ãç°¡åã§ãã ãããã£ãŠãããã«åé¡çªå·1ããããŸãã 決ããå¿ èŠããããŸãã
次ã«ãåé¡çªå·2ããããŸããã QObjectããç¶æ¿ããçŽ æµãªãã³ãã¬ãŒããäœæããŸãããããã¯ãä¿¡å·ã¹ãããéä¿¡ã«å¿ èŠã§ãã ãããŠã ãã€ã¯ãæµ®äžããŸããããMOCã§ã¯ãC ++ã®ãã¹ãŠã®æ©èœã䜿çšã§ããŸããã äž»ãªåé¡ã¯ã ã¯ã©ã¹ãã³ãã¬ãŒãã«ã·ã°ãã«ãŸãã¯ã¹ããããå«ããããšãã§ããªãããšã§ãã ïŒ@ïŒ*ïŒ
ãã ãããã®ãããã¯ãå æããŸããã
ç§ã¯æ¬¡ã®ã¯ã©ã¹ãæãã€ããïŒ
- ãã€ãã£ãã¯ã©ã¹ã¯Tã§ãã
- ãªããžã§ã¯ãäœæã¯ã©ã¹-CreatorBaseïŒQObjectã®åå«ïŒããããŸãã ä»®æ³ã¡ãœãããåŒã³åºãããšã«ããã圌ã¯ã¹ãããã«æ°ãããªããžã§ã¯ããäœæãããã®ã¢ãã¬ã¹ãã·ã°ãã«ã§éä¿¡ããŸãã
- äœæè ã¯ã©ã¹-Creator <T>ïŒCreatorBaseã®åå«ïŒã®ãã³ãã¬ãŒãå®è£ ããããŸãã ç¹å®ã®ã¿ã€ãã®ãªããžã§ã¯ããäœæããã¡ãœãããå®è£ ããŸãã
- æ°ããã¹ã¬ãããäœæããThreadedObjectBaseã¯ã©ã¹ïŒQObjectã®åå«ïŒããããŸãã CreatorBaseäœæè ãåãåããå¿ èŠãªä¿¡å·ã¹ãããéä¿¡ã確ç«ããŸãã
- ãŠãŒã¶ãŒã¯ãªããžã§ã¯ãã®ãã³ãã¬ãŒãã¹ãã¬ãŒãžã¯ã©ã¹ã䜿çšããThreadedObject <T>ïŒThreadedObjectBaseã®åå«ïŒãã¹ããªãŒã ããŸãã æ°ãããªããžã§ã¯ãã®äœæãåŒã³åºãã*ããã³->æŒç®åãããã³äœæããããªããžã§ã¯ãã®ã¿ã€ããã€ã³ã¿ãŒããªãŒããŒããŒãããŸãã
- ãŠãŒã¶ãŒãã¯ã©ã¹ãäœæãïŒQObjectã®åå«ã«ãªãããšãã§ããŸãïŒããªãã·ã§ã³ã§ãclass finished workããšãwork of interruptionãã®ã·ã°ãã«ãå®è£ ãããªããžã§ã¯ãã®é 延åé€ãèšå®ã§ããŸã ã
ã¢ã¯ã·ã§ã³ã®ã·ãŒã±ã³ã¹ã¯åçŽã§ããããšãå€æããŸããã
- ãªããžã§ã¯ããšThreadedObjectã¹ããªãŒã ã®ã¹ãã¬ãŒãžã¯ã©ã¹ã䜿çšãããŸãã
- 圌ã¯ãäœæè ã®äœæè ãšæ°ããã¹ã¬ããã®QThreadãªããžã§ã¯ããäœæããŸãã
- ãªããžã§ã¯ãã®äœæè ãæ°ããã¹ã¬ããã«è»¢éãããŸãã
- ä¿¡å·ã¹ãããéä¿¡ã確ç«ãããŸãã
- æ°ããäœæãããã¹ã¬ããã¯ãå¿ èŠãªåªå 床ã§å§ãŸããŸãã
- äœæãããã¹ã¬ããã«ã«ã¹ã¿ã ã¯ã©ã¹TãäœæãããŸãã
- ThreadedObjectBaseã¯ãsetObjectïŒvoid * ObjïŒã¹ãããã䜿çšããŠããã«ã€ããŠåŠç¿ãããªããžã§ã¯ãã®ã¢ãã¬ã¹ãèšæ¶ããä¿¡å·objectIsReadyïŒïŒã䜿çšããŠããã«ã€ããŠäžçã«éç¥ããŸãã
- ããããã¹ãŠã®ã¢ã¯ã·ã§ã³ã®æ£åžžçµäºã«ã€ããŠã¯ãbool ThreadedObject <T> :: objectIsCreatedïŒvoidïŒconstãåç §ããŠãã ããã
å®è£
äœæãããã¯ã©ã¹ã®ã³ãŒããèæ ®ããŠãã ããïŒãã¹ãŠãç»é¢ã«åãŸãããã«ãã³ã¡ã³ããåé€ããŸããïŒã
ãªããžã§ã¯ãäœæè ïŒ
class CreatorBase: public QObject { Q_OBJECT void *_obj; protected: virtual void *Allocation (void) = 0; public slots: void allocate (void) { emit setObject (Allocation ()); } signals: void setObject (void *Obj); }; template <class T> class Creator: public CreatorBase { protected: void *Allocation (void) { return reinterpret_cast <void*> (new T); } };
ããã§ã¯ãã¹ãŠãæçœã§ããCreatorBaseã¯ãªãšãŒã¿ãŒã®åºæ¬ã¯ã©ã¹ã«ã¯ãæ°ããã¢ã¯ãã£ããªã¹ã¬ããã§èµ·åãããallocateïŒïŒã¹ãããããããŸãã ã·ã°ãã«setObjectïŒvoid * ObjïŒãåŒã³åºããŸããããã¯ãåvoid * Creator <T> :: AllocationïŒïŒã§äœæããããªããžã§ã¯ãã®ã¢ãã¬ã¹ãæž¡ããŸãã
åºåºã¯ã©ã¹ThreadedObjectBaseã¯æ¬¡ã®ãšããã§ãã
class ThreadedObjectBase: public QObject { Q_OBJECT protected: QThread *_thread; virtual void SetObjectPointer (void *Ptr) = 0; ThreadedObjectBase (QObject *parent = 0): QObject (parent), _thread (0) {} void starting (CreatorBase *Creator, QThread::Priority Priority = QThread::InheritPriority, bool ToDeleteLaterThread = true) { bool res; _thread = new QThread; Creator->moveToThread (_thread); res = connect (_thread, SIGNAL (started ()), Creator, SLOT (allocate ())); Q_ASSERT_X (res, "connect", "connection is not established"); res = connect (Creator, SIGNAL (setObject (void*)), this, SLOT (setObject (void*))); Q_ASSERT_X (res, "connect", "connection is not established"); if (ToDeleteLaterThread) { res = connect (_thread, SIGNAL (finished ()), _thread, SLOT (deleteLater ())); Q_ASSERT_X (res, "connect", "connection is not established"); } _thread->start (Priority); } public: virtual ~ThreadedObjectBase (void) { } QThread *thread (void) { return _thread; } const QThread *cthread (void) const { return _thread; } signals: void objectIsReady (void); private slots: void setObject (void *Obj) { SetObjectPointer (Obj); emit objectIsReady (); } };
ããã§ã®äž»ãªæ¹æ³ã¯éå§äžã§ãã æå®ãããåªå 床ã§ã¹ã¬ãããäœæããŸãã èµ·åãããšã_threadã¹ã¬ããã¯QThread :: startedïŒïŒã·ã°ãã«ãåŒã³åºããŸãã ãã®ä¿¡å·ãã¹ãããCreatorBase :: allocateïŒïŒã«é¢é£ä»ããŠãæ°ãããªããžã§ã¯ããäœæããŸãã ããã«ãããä¿¡å·CreatorBase :: setObjectïŒvoid *ïŒãçºçããŸããããã¯ãã¹ãããThreadedObjectBase :: setObjectïŒvoid * ObjïŒã§ååŸããŸãã ãã¹ãŠããªããžã§ã¯ããäœæããïŒããã«ã€ããŠä¿¡å·ThreadedObjectBase :: objectIsReadyïŒïŒãçºè¡ãããŸãïŒããªããžã§ã¯ããžã®ãã€ã³ã¿ãŒãåä¿¡ãããŸãã
ãŠãŒã¶ãŒãã¹ã¬ããã¯ã©ã¹ã®é 延åé€ïŒæãŸããïŒãèšå®ããå Žåãæ¥ç¶ã¯_thread QThread :: finish ïŒïŒ -> QObject :: deleteLaterïŒïŒå ã§ç¢ºç«ãããŸãã
ãŸãããŠãŒã¶ãŒã¯ä¿¡å·ã®ååãèšå®ã§ããŸãïŒå€æ°_finished_signalã«æ ŒçŽãããŸãïŒã ãã®ã·ã°ãã«ã¯ãäœæããããªããžã§ã¯ãã®äœæ¥çµäºæã«åŒã³åºãããŸãã åæ§ã«ã_terminate_slotããã®ã¹ãããã¯ãã¹ã¬ããå²ã蟌ã¿ã·ã°ãã«ã«ãã£ãŠåŒã³åºãããŸãïŒãã ããã¹ã¬ããã¯å³åº§ã«åæ¢ããŸãããã¹ã¬ããïŒïŒ-> waitãåç §ããŠãçµäºããã®ãåŸ ã€ããšãã§ããŸã-QThread :: waitãåç §ïŒã
æåŸã«ããŠãŒã¶ãŒã«è¡šç€ºããããã³ãã¬ãŒãã¯ã©ã¹ïŒ
template <class T> class ThreadedObject: public ThreadedObjectBase { protected: T* _obj; Creator<T> _creator; const char *_finished_signal; const char *_terminate_slot; bool _to_delete_later_object; void SetObjectPointer (void *Ptr) { bool res; _obj = reinterpret_cast <T*> (Ptr); if (_finished_signal) { res = connect (_obj, _finished_signal, _thread, SLOT (quit ())); Q_ASSERT_X (res, "connect", "connection is not established"); } if (_terminate_slot) { res = connect (_thread, SIGNAL (finished ()), _obj, _terminate_slot); Q_ASSERT_X (res, "connect", "connection is not established"); } if (_to_delete_later_object && _finished_signal) { res = connect (_obj, _finished_signal, _obj, SLOT (deleteLater ())); Q_ASSERT_X (res, "connect", "connection is not established"); } } public: ThreadedObject (QObject *parent = 0): ThreadedObjectBase (parent), _obj (0) { } ~ThreadedObject (void) { } void start (const char *FinishedSignal = 0, const char *TerminateSlot = 0, QThread::Priority Priority = QThread::InheritPriority, bool ToDeleteLaterThread = true, bool ToDeleteLaterObject = true) { Creator<T> *creator = new Creator<T>; _finished_signal = FinishedSignal; _terminate_slot = TerminateSlot; _to_delete_later_object = ToDeleteLaterObject; starting (_creator, Priority, ToDeleteLaterThread); delete creator; } bool objectIsCreated (void) const { return _obj != 0; } T* ptr (void) { return reinterpret_cast <T*> (_obj); } const T* cptr (void) const { return reinterpret_cast <const T*> (_obj); } // . operator T* (void) { return ptr (); } T* operator -> (void) { return ptr (); } operator const T* (void) const { return cptr (); } const T* operator -> (void) const { return cptr (); } };
ããã§ãã¡ã€ã³ã®ã¡ãœããã¯startã§ããããã¯ã·ã°ãã«ãšã¹ãããã®ååãèšæ¶ããã¡ãœããã®é 延åé€ãèšå®ããŸãã objectIsCreatedïŒïŒã¡ãœããã¯ããªããžã§ã¯ããæ¢ã«äœæãããŠããå Žåã«trueãè¿ããŸãã è€æ°ã®ãªãŒããŒããŒãã«ãããThreadedObject <T>ãã¹ããŒããã€ã³ã¿ãŒãšããŠäœ¿çšã§ããŸãã
ãããã®ã¯ã©ã¹ã䜿çšããç°¡åãªäŸã次ã«ç€ºããŸãã
ThreadedObject <Operation> _obj; QObject::connect (&_obj, SIGNAL (objectIsReady ()), this, SLOT (connectObject ())); _obj.start (SIGNAL (finished ()), SLOT (terminate ()), QThread::HighPriority);
å®éã®äŸã以äžã«æ·»ä»ããŸã-ã¡ã€ã³ã¹ã¬ããã«ãã¿ã³ãäœæãããŸãã intå€æ°ã¯ãæ°ããã¹ã¬ããã§äœæãããã¿ã€ããŒããã®ã·ã°ãã«ãšã¿ã€ããŒã€ãã³ããäœæãããŸãã ãããã®ã¿ã€ããŒã¯äž¡æ¹ãšãintå€æ°ã®å€ãæžãããŸã;ãŒãã«éãããšã QCoreApplication :: quitïŒïŒã¹ããããåŒã³åºãããŸãã äžæ¹ãã¢ããªã±ãŒã·ã§ã³ãéãããšãã¹ã¬ãããåæ¢ããŸãã WinXPã§ãã¹ããããäŸã LinuxãMacOSãAndroidãããã³ãã®ä»ã®ãµããŒããããŠãããã©ââãããã©ãŒã ã§ã®æåãããã¹ãã«ã€ããŠã®ã³ã¡ã³ããèãããã§ã ã
äŸ+ã¯ã©ã¹
ThreadedObjectãã¡ã€ã«ïŒ
Main.cppãã¡ã€ã«ïŒ
// ** // ** // ** class CreatorBase: public QObject { Q_OBJECT void *_obj; // protected: virtual void *Allocation (void) = 0; // public slots: void allocate (void) { emit setObject (Allocation ()); } // signals: void setObject (void *Obj); // }; // ** // ** // ** class ThreadedObjectBase: public QObject { Q_OBJECT protected: QThread *_thread; // virtual void SetObjectPointer (void *Ptr) = 0; // ThreadedObjectBase (QObject *parent = 0): QObject (parent), _thread (0) {} // void starting (CreatorBase *Creator, QThread::Priority Priority = QThread::InheritPriority, bool ToDeleteLaterThread = true) // { bool res; // - _thread = new QThread; // Creator->moveToThread (_thread); // _creator res = connect (_thread, SIGNAL (started ()), Creator, SLOT (allocate ())); Q_ASSERT_X (res, "connect", "connection is not established"); // _thread Creator- res = connect (Creator, SIGNAL (setObject (void*)), this, SLOT (setObject (void*))); Q_ASSERT_X (res, "connect", "connection is not established"); // Creat- if (ToDeleteLaterThread) // thread? { res = connect (_thread, SIGNAL (finished ()), _thread, SLOT (deleteLater ())); Q_ASSERT_X (res, "connect", "connection is not established"); } // _thread _thread->start (Priority); // } public: // . virtual ~ThreadedObjectBase (void) { } // QThread *thread (void) { return _thread; } // , // . const QThread *cthread (void) const { return _thread; } // , signals: void objectIsReady (void); // " " private slots: void setObject (void *Obj) { SetObjectPointer (Obj); emit objectIsReady (); } // }; // class ThreadedObjectBase // ** // ** // ** template <class T> class ThreadedObject: public ThreadedObjectBase { private: template <class T> class Creator: public CreatorBase // { protected: void *Allocation (void) { return reinterpret_cast <void*> (new T); } }; protected: T* _obj; // Creator<T> _creator; // const char *_finished_signal; // " " const char *_terminate_slot; // " " bool _to_delete_later_object; // " ? void SetObjectPointer (void *Ptr) // { bool res; // - _obj = reinterpret_cast <T*> (Ptr); // if (_finished_signal) // " "? { res = connect (_obj, _finished_signal, _thread, SLOT (quit ())); Q_ASSERT_X (res, "connect", "connection is not established"); } // if (_terminate_slot) // " "? { res = connect (_thread, SIGNAL (finished ()), _obj, _terminate_slot); Q_ASSERT_X (res, "connect", "connection is not established"); } // " " if (_to_delete_later_object && _finished_signal) // ? { res = connect (_obj, _finished_signal, _obj, SLOT (deleteLater ())); Q_ASSERT_X (res, "connect", "connection is not established"); } // } public: // . ThreadedObject (QObject *parent = 0): ThreadedObjectBase (parent), _obj (0) {} // ~ThreadedObject (void) { } // void start (const char *FinishedSignal = 0, const char *TerminateSlot = 0, QThread::Priority Priority = QThread::InheritPriority, bool ToDeleteLaterThread = true, bool ToDeleteLaterObject = true) // { _finished_signal = FinishedSignal; // " " _terminate_slot = TerminateSlot; // " " _to_delete_later_object = ToDeleteLaterObject; // starting (_creator, Priority, ToDeleteLaterThread); // } // . bool objectIsCreated (void) const { return _obj != 0; } // ? T* ptr (void) { return reinterpret_cast <T*> (_obj); } // const T* cptr (void) const { return reinterpret_cast <const T*> (_obj); } // // . operator T* (void) { return ptr (); } // T* operator -> (void) { return ptr (); } // operator const T* (void) const { return cptr (); } // const T* operator -> (void) const { return cptr (); } // }; // class ThreadedObject
Main.cppãã¡ã€ã«ïŒ
#include <QtGui> #include <QtWidgets> #include <QtCore> #include "ThreadedObject.h" // ** // ** // ** class Operation: public QObject { Q_OBJECT int *Int; // QTimer _tmr; // int _int_timer; // public: Operation (void) { Int = new int (5); } // ~Operation (void) { if (Int) delete Int; } // signals: void addText(const QString &txt); // " " void finished (); // " " public slots: void terminate () // { killTimer (_int_timer); // _tmr.stop (); // delete Int; // Int = 0; // emit finished (); // } void doAction (void) // { bool res; emit addText (QString ("- %1 -"). arg (*Int)); res = QObject::connect (&_tmr, &QTimer::timeout, this, &Operation::timeout); Q_ASSERT_X (res, "connect", "connection is not established"); // _tmr.start (2000); // thread()->sleep (1); // 1 ... timeout (); // ... ... startTimer (2000); // ... } protected: void timerEvent (QTimerEvent *ev) { timeout (); } // private slots: void timeout (void) { if (!Int || !*Int) // ? return; // ... --*Int; // emit addText (QString ("- %1 -"). arg (*Int)); // if (!Int || !*Int) // ? emit finished (); // ... } }; // ** // ** , // ** class App: public QObject { Q_OBJECT ThreadedObject <Operation> _obj; // - QPushButton _btn; // protected: void timerEvent (QTimerEvent *ev) { bool res; // - killTimer (ev->timerId ()); // res = QObject::connect (&_obj, SIGNAL (objectIsReady ()), this, SLOT (connectObject ())); Q_ASSERT_X (res, "connect", "connection is not established"); // _obj.start (SIGNAL (finished ()), SLOT (terminate ()), QThread::HighPriority); // } private slots: void setText (const QString &txt) { _btn.setText (txt); } // void connectObject (void) // { bool res; // - res = QObject::connect (this, &App::finish, _obj, &Operation::terminate); Q_ASSERT_X (res, "connect", "connection is not established"); // res = QObject::connect (this, &App::startAction, _obj, &Operation::doAction); Q_ASSERT_X (res, "connect", "connection is not established"); // res = QObject::connect (_obj, &Operation::finished, this, &App::finish); Q_ASSERT_X (res, "connect", "connection is not established"); // res = QObject::connect (_obj, &Operation::addText, this, &App::setText); Q_ASSERT_X (res, "connect", "connection is not established"); // res = QObject::connect (&_btn, &QPushButton::clicked, _obj, &Operation::terminate); Q_ASSERT_X (res, "connect", "connection is not established"); // _btn.show (); // emit startAction (); // } public slots: void terminate (void) { emit finish (); } // signals: void startAction (void); // " " void finish (void); // " " }; // ** // ** // ** int main (int argc, char **argv) { QApplication app (argc, argv); // App a; // bool res; // a.startTimer (0); // res = QObject::connect (&a, SIGNAL (finish ()), &app, SLOT (quit ())); Q_ASSERT_X (res, "connect", "connection is not established"); // res = QObject::connect (&app, SIGNAL (lastWindowClosed ()), &a, SLOT (terminate ())); Q_ASSERT_X (res, "connect", "connection is not established"); // return app.exec(); // } #include "main.moc"