2010-01-20 18 views
5

현재 파이썬 asyncore 및 pyqt4를 사용하여 네트워킹을 배우려고합니다.QObject (QPlainTextEdit) 및 멀티 스레드 문제

기본적으로 일부 포트에서 수신 대기하는 작은 서버를 코딩하고 보낸 사람에게받는 모든 메시지를 다시 보냅니다.

qts QApplication.exec_()asyncore.loop()은 둘 다 하나의 스레드에서 시작할 수없는 함수이므로 asyncore.loop()을 별도의 데몬 스레드에서 보았습니다. (asyncore.dispatcher에서 파생 된) 내 서버 클래스를 설정하거나 연결을 끊거나 /를 보낼 때마다

IT는 QPlainTextEdit의 정보를 표시합니다 (QtGui.QMainWindow에서 파생 된) 내 창 클래스의 메소드를 호출, 메시지를 받으면에.

하지만 텍스트를 마우스로 표시하지 않으면 텍스트가 표시되지 않습니다. 오류 MSG 다음

파이썬 콘솔 표시 :

QObject::connect: Cannot queue arguments of type 'QTextBlock' 
(Make sure 'QTextBlock' is registered using qRegisterMetaType().) 
QObject::connect: Cannot queue arguments of type 'QTextCursor' 
(Make sure 'QTextCursor' is registered using qRegisterMetaType().) 

나는이가 일반 함수 호출의 & 슬롯을 사용하는 대신 신호, 다른 스레드에서 QT-함수를 호출하여 것을 야기 될 수 있음을, 어떤 포럼에 읽을 수 있습니다 문제를 해결할 수 있지만 신호를 시도하고 난 여전히이 오류가 발생합니다.

그래서 (정말로 내 문제의 원인 인 경우) 다른 스레드에서 qt 개체의 메서드를 호출하는 올바른 방법은 무엇입니까?

편집 추가 정보 : asyncore.loop() 호출이 자식 스레드에 위치하고 있으며, 물론 그 정말로 차단하지,하지만 asyncore.loop의 실행 중() 내 서버 클래스 (asyncore.dispatcher) 네트워킹을 할 수 있습니다. 그래서 asyncore.loop()의 런타임 중에 asyncore.loop() (자식 스레드)에 의해 내 서버 클래스의 메소드가 호출되고이 중 i 은 주 스레드에서 실행중인 윈도우 클래스에 신호를 보내려고했습니다

편집 : 지금 코드가 작동하는 것처럼 보입니다. 코드에 오류가 있습니다. 모든 신호가 의도 된대로 작동합니다.

편집 : 작은 예 : http://paste2.org/p/635612 (죽은 링크)

+0

해결 방법에 대한 설명이나 스 니펫을 게시 할 수 있습니까? 그것은 미래에 같은 문제를 가진 다른 사람들을 도와 줄 것입니다. =) –

답변

8

당신이 메인 스레드가 아닌 다른 스레드에서 QtGui 클래스에 액세스하려는 나타납니다. 다른 GUI 툴킷 (예 : 자바 스윙)과 마찬가지로 허용되지 않습니다. Threads and QObjects 웹 페이지에서 :

QObject를 재진입이 있지만, GUI 클래스, 특히는 QWidget과 모든 서브 클래스는, 재진입하지 않습니다. 그들은 메인 스레드에서만 사용할 수 있습니다.

해결 방법은 주 스레드 (GUI 개체가있는 곳)와 보조 스레드 (들) 사이의 통신을 위해 신호와 슬롯을 사용하는 것입니다. 기본적으로 다른 스레드를 통해 QObject로 전달되는 신호를 하나의 스레드에서 방출합니다. 위에 링크 된 페이지에는 이에 대한 좋은 토론이 있습니다. 실제로, Thread Support in Qt의 전체 섹션은 좋은 읽을 거리입니다.

하나의 잠재적 인 문제는 일반적으로 전체 신호와 슬롯이 스레드를 통한 작업을 지원한다는 것이며, 신호가 발생할 수 있도록 QThread::exec() (또는 PyQt 등가물)을 사용하여 자식 스레드에서 이벤트 루프를 시작해야한다는 것입니다. 거기에 사는 QObject의 슬롯에 전달 될 수 있습니다. 귀하의 경우에는 asyncore.loop()에 대한 막힘 전화를하는 것처럼 들리므로이를 방지 할 수 있습니다. 하지만, 한 방향 (자식 스레드에서 메인 스레드의 위젯까지)에서 신호를 내 보내기 만하면 문제가 발생할 것이라고 생각하지 않습니다.

+1

오류 메시지는 그가 신호/슬롯 연결을 시도 함을 나타냅니다. 그러나 QTextBlock 데이터 형식은 등록 된 QMetaType이 아니므로 스레드간에 연결을 통해 전달할 수 없습니다. – e8johan

+0

QThreads를 완전히 잊어 버린 것을 잊어 버렸습니다. QThreads'exec() _'메소드가 다시 블로킹 메서드이기 때문에 어떻게 QThreads를 사용할 수 있습니까? 그렇습니다. 내 서버 클래스와 같은 스레드에서 실행할 수 없습니다. .
@ e8johan : 신호를 사용하지 않을 때와 같은 오류 메시지가 나타납니다. – smerlin