我正在创建一个通信 GUI,它使用我无法发布的导入的 tx 和 rx python 脚本发送和接收消息。我已经独立测试了它们,它们按预期工作。我希望 GUI 的工作方式是打开一个 tx GUI 和一个 rx GUI。当选择 tx 单选按钮并且用户点击发送时,它会调用 tx 脚本并将消息发送到 rx 脚本接收到的位置,并显示在底部 TextCtrl 框中。
我相信我必须使用线程来运行 rx 脚本,因为 tx 脚本在主线程中运行。您会注意到,当选择 rx 单选按钮时,我会创建线程,因此它只会发生一次。但是,我希望每次收到新消息时都调用 receive_msg 函数,以便更新 TextCtrl 框。如何在不创建多个线程的情况下做到这一点?
我尝试将receed_msg函数绑定到发送按钮,但没有帮助。
import wx
import tx_UDP
import rx_UDP
import threading
class ExamplePanel(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self,parent, title=title, size=(600,600))
self.InitUI()
def InitUI(self):
pn1 = wx.Panel(self)
self.quote = wx.StaticText(pn1, label="Please select transmission direction:", pos=(20, 30))
# A multiline TextCtrl
self.rx_box = wx.TextCtrl(pn1, pos=(20, 370), size=(500,100), style=wx.TE_MULTILINE | wx.TE_READONLY)
self.tx_box = wx.TextCtrl(pn1, pos=(20,110), size=(500,200), style=wx.TE_MULTILINE)
#self.logger = wx.TextCtrl(self, pos=(300,20), size=(200,300), style=wx.TE_MULTILINE | wx.TE_READONLY)
# Send button
self.send_button = wx.Button(pn1, label="Send", pos=(450, 325))
self.send_button.Bind(wx.EVT_BUTTON, self.OnSendClick)
# TX & RX Radio Boxes
tx_rx = ['TX','RX']
self.rb = wx.RadioBox(pn1, label="", pos=(20, 50), choices=tx_rx, majorDimension=2, style=wx.RA_SPECIFY_COLS)
self.rb.Bind(wx.EVT_RADIOBOX, self.EvtRadioBox)
self.Show(True)
def EvtRadioBox(self,event):
rb_index = self.rb.GetSelection()
# TX
if rb_index == 0:
self.send_button.Enable()
self.tx_box.Enable()
# RX
else:
self.send_button.Disable()
self.tx_box.Disable()
t=threading.Thread(target=self.Recieved_msg)
t.start()
def OnSendClick(self, event):
message = self.tx_box.GetValue()
tx_UDP.tx_UDP(message)
def Recieved_msg(self, event=None):
recieved_msg = rx_UDP.rx_UDP()
self.rx_box.SetValue(recieved_msg)
您还没有发布可行的代码,因此无需重新发明轮子,我怀疑您将能够使用
wx.lib.newevent
来发布您自己的events
,以通常的方式在主循环中将其绑定到。
当您收到事件时,您可以使用您在事件中收到的任何消息更新相应的文本控件。
这里有一个例子供你选择。
from threading import Thread
import wx
import time
import wx.lib.newevent
progress_event, EVT_PROGRESS_EVENT = wx.lib.newevent.NewEvent()
class WorkThread(Thread):
def __init__(self,parent_target):
"""Init Worker Thread Class."""
Thread.__init__(self)
self.target = parent_target
self.stop_work_thread = 0
self.start() # start the thread
def run(self):
curr_loop = 0
while True:
if self.stop_work_thread == 1: # Exit
break
time.sleep(1)
if self.stop_work_thread == 2: # Paused
continue
curr_loop += 1
evt = progress_event(count=curr_loop,name=self.name)
#Send back current count for the progress bar
try:
wx.PostEvent(self.target, evt)
except: # The parent frame has probably been destroyed
self.stop()
return
def stop(self):
self.stop_work_thread = 1
def pause(self):
if self.stop_work_thread == 2:
self.stop_work_thread = 0
self.target.pause_btn.SetLabel('Pause')
else:
self.stop_work_thread = 2
self.target.pause_btn.SetLabel('Paused')
class Progress(wx.Frame):
def __init__(self, parent, title):
super(Progress, self).__init__(parent, title = title,size = (500,300))
left_sizer = wx.BoxSizer(wx.VERTICAL)
middle_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.panel = wx.Panel(self)
self.start_btn = wx.Button(self.panel, label="Start")
self.stop_btn =wx.Button(self.panel, label="Stop")
self.count_btn =wx.Button(self.panel, label="Count")
self.pause_btn =wx.Button(self.panel, label="Pause")
self.quit_btn =wx.Button(self.panel, label="Quit")
self.logger = wx.TextCtrl(self.panel, size=(200,200), style=wx.TE_MULTILINE | wx.TE_READONLY)
self.stop_btn.Disable()
self.count_btn.Disable()
self.pause_btn.Disable()
left_sizer.Add(self.start_btn,0,wx.EXPAND)
left_sizer.Add(self.stop_btn,0,wx.EXPAND)
left_sizer.Add(self.count_btn,0,wx.EXPAND)
left_sizer.Add(self.pause_btn,0,wx.EXPAND)
left_sizer.Add(self.quit_btn,0,wx.EXPAND)
middle_sizer.Add(self.logger,0,wx.EXPAND)
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.mainsizer.Add(left_sizer)
self.mainsizer.Add(middle_sizer)
self.panel.SetSizer(self.mainsizer)
self.Layout()
self.start_btn.Bind(wx.EVT_BUTTON, self.onStart)
self.stop_btn.Bind(wx.EVT_BUTTON, self.onCancel)
self.pause_btn.Bind(wx.EVT_BUTTON, self.onPause)
self.quit_btn.Bind(wx.EVT_BUTTON, self.onExit)
#Bind to the progress event issued by the thread
self.Bind(EVT_PROGRESS_EVENT, self.OnProgress)
self.Bind(wx.EVT_CLOSE, self.onExit)
def OnProgress(self, event):
if not self.work.is_alive():
return
step = event.count
ident = event.name
s_step = ident+" count "+str(step)+'\n'
self.logger.AppendText(s_step)
self.count_btn.SetLabel("Count "+str(step))
def onStart(self, event):
self.start_btn.Disable()
self.work = WorkThread(parent_target=self)
self.pause_btn.Enable()
self.stop_btn.Enable()
def onPause(self, event):
if self.work.is_alive():
self.work.pause() # Pause the thread
def onCancel(self, event):
"""Cancel thread process"""
try:
self.work.stop()
self.work.join()
except:
pass
self.onFinish()
def onFinish(self):
"""thread process finished - clean up"""
self.start_btn.Enable()
self.stop_btn.Disable()
self.pause_btn.Disable()
self.pause_btn.SetLabel("Pause")
self.count_btn.SetLabel("Count")
self.logger.Clear()
def onExit(self, event):
self.onCancel(None)
self.onFinish()
self.Destroy()
app = wx.App()
frame = Progress(None,'Thread Incrementer')
frame.Show()
app.MainLoop()