1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[解決]wxPythonとthreadingを同時に使ったら失敗した

Last updated at Posted at 2021-04-01

#wxPythonとthreadingを使ったら...
これはWindowsに限った話です。
Python無知がwxPythonとthreadingを使ったらおかしなことになりました。
このコードをご覧ください。↓

import wx
import time
import threading
class MyFrame(wx.Frame):
    def TimeSleep(self,value=0):
        time.sleep(value)
        self.OnStart()
    def __init__(self):
        wx.Frame.__init__(self,None,-1,"title")
        self.panel = wx.Panel(self,-1)
        self.panel.SetBackgroundColour("black")
        self.Refresh()
        t1=threading.Thread(target=self.TimeSleep,args=(2,))
        t1.start()
    def OnStart(self):
        self.panel.SetBackgroundColour("white")
        lbl = wx.StaticText(self.panel,-1,"Finish")
        self.Refresh()
app = wx.App(False)
f = MyFrame()
f.Show(True)
app.MainLoop()

これで実行した結果、なんと[Finish]が表示されないというバグに至ってしまいました...
どいうことかというと、threadingを使った後、新しいウィジェットが表示されなくなったということです。
また、threadingと同時にwx.Timerも使えないということです。
色々と試した結果原因と解決方法が見つかったので説明したいと思います。

#原因
キャプチャa.PNG
無知なのでこういう図もどう作ればいいかわからなくて...

っでまあこのように外にいってその外からメインのGUIを操作できないということでした。
それで新しいウィジェットをつくれない!ということでした。プログラミングって難しい...
それで直接wxPython, threadingで調べてみてもこのことがかかれていなかったのでめちゃめちゃ苦労しました。それでたまたま見つかった関数があってそれが「wx.CallAfter」です。

#解決方法
さきほどいった通り、wx.CallAfterを使用して、外からメインのGUIに戻るということです。
それで以下のようなコードになりました。

import wx
import time
import threading
class MyFrame(wx.Frame):
    def TimeSleep(self,value=0):
        time.sleep(value)
        wx.CallAfter(self.OnStart) ##ここ!
    def __init__(self):
        wx.Frame.__init__(self,None,-1,"title")
        self.panel = wx.Panel(self,-1)
        self.panel.SetBackgroundColour("black")
        self.Refresh()
        t1=threading.Thread(target=self.TimeSleep,args=(2,))
        t1.start()
    def OnStart(self):
        self.panel.SetBackgroundColour("white")
        lbl = wx.StaticText(self.panel,-1,"Finish")
        self.Refresh()
app = wx.App(False)
f = MyFrame()
f.Show(True)
app.MainLoop()

#おわりに
これ解決するのに何カ月もかかりました 笑
これ環境によってはこの方法をつかわなくてもできたということもありますし、もしくはバージョンによっても変わるということがあるのでその場合は使わなくてもいいです(でも外からGUIをいじるのは安全ではないので使うことを推奨します。)


ブログ開設しときました。まだ全然記事あげてませんが、これから色々とあげる予定です。是非見に来てください。→ programming-self-study.blogspot.com/

###環境
Python 3.9.1
Windows10
64bit

誤字あったら教えてね!

1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?