2017-04-11 5 views
0

윈도우 7, 64 비트, MSYS2 Mingw64 쉘 (쉘 시작 명령은 C:\msys64\msys2_shell.cmd -use-full-path -mingw64)에서 테스트 중입니다. 여기에 pacman : mingw-w64-x86_64-python2-2.7.13-1, mingw-w64-x86_64-wxWidgets-3.0.2-17mingw-w64-x86_64-wxPython-3.0.2.0-6을 통해 설치했습니다.MSYS2의 wxPython : 스레드 처리기의 SetLabel이 동결됩니까?

제목 레이블, 단추 및 대상 레이블 만있는이 코드를 고려하십시오. 버튼을 클릭하면, 라벨은 "X"에서 "1"로 변경한다 : 나는 그대로이 코드를 실행하면

import wx #, wx.html 
import sys, os 
from threading import Thread 

# disable buffering (Windows) 
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) 
sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 0) 

class Frame(wx.Frame): 
    def __init__(self, *args, **kwds): 
    kwds["style"] = wx.DEFAULT_FRAME_STYLE 
    wx.Frame.__init__(self, *args, **kwds) 

    self.label = wx.StaticText(self, wx.ID_ANY, "Click the button to change label below: ") 
    self.bt_main = wx.Button(self, label="Click ME") 
    self.bt_main.Bind(wx.EVT_BUTTON, self.BtnClickHandler) 
    self.label2 = wx.StaticText(self, wx.ID_ANY, "XX") 

    sizer_vmain_app = wx.BoxSizer(wx.VERTICAL) 
    sizer_vmain_app.Add(self.label, proportion=0, flag=wx.EXPAND, border=0) 
    sizer_vmain_app.Add(self.bt_main, proportion=0, flag=0, border=0) 
    sizer_vmain_app.Add(self.label2, proportion=0, flag=0, border=0) 

    self.SetSizer(sizer_vmain_app) 
    self.Layout() 

    def BtnClickHandler(self, event): 
    testThread = Thread(target=self.DoBtnClick) 
    testThread.start() 
    testThread.join() 

    def DoBtnClick(self): 
    print("BtnClickHandler ") 
    myval = int("1") 
    self.label2.SetLabel(str(myval)) 

if __name__ == "__main__": 
    app = wx.PySimpleApp(0) 
    wx.InitAllImageHandlers() 
    app_frame = Frame(None, wx.ID_ANY, "") 
    app.SetTopWindow(app_frame) 
    app_frame.Show() 
    app.MainLoop() 

는 다음 응용 프로그램이 정지 그것은 self.label2.SetLabel(str(myval))에 관해서. 내가 대신이 기능을 스레딩을 피하고, 사용하는 경우

그러나 :

def BtnClickHandler(self, event): 
    # testThread = Thread(target=self.DoBtnClick) 
    # testThread.start() 
    # testThread.join() 
    self.DoBtnClick() 

은 ... 다음 모든 작동합니다. 이 스크립트는 MSYS2 Mingw64 셸에서 python test.py을 실행하여 호출합니다.

Windows에서 스레딩을 사용하여이 코드를 실행할 수 있습니까? 그렇다면 어떻게해야합니까? (그렇지 않으면 리눅스에서 쓰레딩과 함께 문제없이 실행됩니다)

+1

wxpython 데모를 보셨습니까? – Igor

+0

고마워요 @ 로고 - 아니, 그게 무슨 차이가 있니? 그게 어떻게이 문제에 도움이됩니까? – sdaau

+0

죄송합니다. 내 대답은 아래를 참조하십시오. – Igor

답변

0

문제는 wxWidgets 라이브러리가 스레드로부터 안전하지 않다는 것입니다.

의미는 보조 스레드에서 GUI 요소에 액세스 할 수 없다는 것입니다. GUI 액세스는 응용 프로그램 객체를 만든 주 스레드에서만 지원됩니다.

0

GUI에 영향을 미치는 메소드를 주 스레드가 아닌 다른 스레드에서 호출 할 수 없습니다. 대신 작업자 스레드 대신 필요한 작업을 수행하도록 요청하는 이벤트를 주 스레드에 게시하십시오.

C++에서 가장 간단한 방법은 CallAfter()을 람다 (예 : Lambda)와 함께 사용하는 것입니다. 당신은 스레드 코드에서 CallAfter([=](){ label2->SetLabel(myval); })을 할 수 있습니다. 불행히도 이것이 파이썬에서 사용 가능한지 모르겠습니다.