我正在尝试将一个线程中的值打印到另一个类中定义的TextCtrl窗口中。发布的代码是一个精简版本,它将在后台线程中增加一个值,然后尝试将其打印到TextCtrl窗口失败。
我尝试使用pubsub,但无法找到一个足够接近我的代码的示例来整合"。
更新
我已将我的线程添加到自己的类中,现在我收到错误。
如何使用post事件将数据发送到另一个类的textCtrl框?
import wx
import time
import threading
GlobalVar = False
#draws the GUI
class Mywin(wx.Frame):
def __init__(self, parent, title):
#Frame
super(Mywin, self).__init__(parent, title = title,size = (500,300))
panel = wx.Panel(self)
#Constant stream toggle Button
self.tbtn =wx.ToggleButton(self, label="Constant Stream", pos=(20, 90))
self.tbtn.Bind(wx.EVT_TOGGLEBUTTON, self.OnToggle)
#Text window
self.logger = wx.TextCtrl(self, pos=(150,0), size=(400,100), style=wx.TE_MULTILINE | wx.TE_READONLY)
#Draws and laysout the GUI
panel.Layout()
self.Centre()
self.Show()
self.Fit()
#=====================================================================
def OnToggle(self,event): #Toggle on, start background stream
state = event.GetEventObject().GetValue()
global GlobalVar
if state == True:
GlobalVar = True
Stream.start()
event.GetEventObject().SetLabel("Streaming")
else:
GlobalVar = False
event.GetEventObject().SetLabel("Constant Stream")
class StreamThread(threading.Thread):
def __init__(self, threadID, name):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
def run(self):
global GlobalVar
IncrementMe = 0
while GlobalVar == True:
wx.PostEvent(Mywin.logger.AppendText(str(IncrementMe)))
print(IncrementMe)
time.sleep(1)
IncrementMe = IncrementMe + 1
Stream = StreamThread(1, "Stream_Thread")
Stream.daemon = True
app = wx.App()
Mywin(None, 'Incrementer')
app.MainLoop()
del app
答案 0 :(得分:0)
为了让这个工作正常并且你已经接受了一个全局变量,只需将logger
设为全局变量,而不是self.logger
。
注意self.logger.AppendText(IncrementMe)
必须变为logger.AppendText(str(IncrementMe))
,因为追加int
会让您感到悲伤。
理想情况下,您应该重新启用此选项以将thread
作为Class
,然后您可以使用wx.PostEvent
通过绑定到事件来触发MyWin
中的操作。 />
请参阅:https://wxpython.org/Phoenix/docs/html/events_overview.html
https://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/
编辑: 这是一个pubsub脚本,希望能指出你正确的方向。
from threading import Thread
import wx
from wx.lib.pubsub import pub
import time
class WorkThread(Thread):
def __init__(self):
"""Init Worker Thread Class."""
Thread.__init__(self)
self.stop_work_thread = 0
self.start() # start the thread
self.val = 0
def run(self):
while True:
if self.stop_work_thread == 1:
break
time.sleep(1)
self.val += 1
wx.CallAfter(pub.sendMessage, "update", step=self.val)
wx.CallAfter(pub.sendMessage, "finish")
return
def stop(self):
self.stop_work_thread = 1
class Progress(wx.Frame):
def __init__(self, parent, title):
super(Progress, self).__init__(parent, title = title,size = (500,300))
self.panel = wx.Panel(self)
self.start_btn = wx.Button(self.panel, label="Start", pos=(20,50))
self.start_btn.Bind(wx.EVT_BUTTON, self.onStart)
self.stop_btn =wx.ToggleButton(self.panel, label="Stop", pos=(20, 90))
self.stop_btn.Bind(wx.EVT_TOGGLEBUTTON, self.onCancel)
self.logger = wx.TextCtrl(self.panel, pos=(150,0), size=(200,200), style=wx.TE_MULTILINE | wx.TE_READONLY)
self.stop_btn.Disable()
self.Bind(wx.EVT_CLOSE, self.onExit)
def onUpdate(self, step):
step = str(step)+'\n'
self.logger.AppendText(step)
def onStart(self, event):
self.logger.Clear()
pub.subscribe(self.onUpdate, "update")
pub.subscribe(self.onFinish, "finish")
btn = event.GetEventObject()
self.start_btn.Disable()
self.work = WorkThread()
Progress(self.panel,'Incrementer')
self.stop_btn.Enable()
def onCancel(self, event):
"""Cancel thread process"""
try:
self.work.stop()
self.work.join()
except:
pass
def onFinish(self):
"""thread process finished"""
try:
pub.unsubscribe(self.onUpdate, "update")
pub.unsubscribe(self.onFinish, "finish")
except:
pass
self.start_btn.Enable()
self.stop_btn.Disable()
def onExit(self, event):
self.onCancel(None)
self.onFinish()
self.Destroy()
app = wx.App()
frame = Progress(None,'Incrementer')
frame.Show(True)
app.MainLoop()