如何将信息从wxPython线程发送到twisted线程
我有一个似乎无法解决的问题。这个问题与我正在构建的wxPython/twisted应用程序有关。此应用程序执行以下功能。当用户单击按钮时,此应用程序将启动gui wxPython窗口。然后启动一个新线程,通过ssl连接到TwistedTCP服务器。此连接是恒定的,在用户运行GUI时将保持连接。从服务器发送到gui客户端的任何数据都会使用wx.lib.pubsub显示在gui中。我所描述的项目工作正常 我的问题是: 我有一个wxPython组合框,它根据从连接到的服务器发送到客户机的数据填充。我有一个事件,当在组合框中选择某个内容时,该信息(选择)应发送到服务器。我不知道怎么做。我的意思是,我从combobox(self.combo\u box\u 1.GetValue())中选择了值,但不知道如何将该信息发送到运行在不同线程中的twisted reactor中。这简直要了我的命。我已经搜索过如何做到这一点,但不知道如何让它在不同线程中使用一个持续运行的套接字。欢迎提供任何帮助/示例 这是我正在使用的代码如何将信息从wxPython线程发送到twisted线程,python,multithreading,client,twisted,Python,Multithreading,Client,Twisted,我有一个似乎无法解决的问题。这个问题与我正在构建的wxPython/twisted应用程序有关。此应用程序执行以下功能。当用户单击按钮时,此应用程序将启动gui wxPython窗口。然后启动一个新线程,通过ssl连接到TwistedTCP服务器。此连接是恒定的,在用户运行GUI时将保持连接。从服务器发送到gui客户端的任何数据都会使用wx.lib.pubsub显示在gui中。我所描述的项目工作正常 我的问题是: 我有一个wxPython组合框,它根据从连接到的服务器发送到客户机的数据填充。我有
import wx
from wx.lib.pubsub import pub
from wx.lib.pubsub import setupkwargs
import gettext
from OpenSSL import SSL
from twisted.internet import ssl, reactor
from twisted.internet.protocol import ClientFactory, Protocol
import time
from Service_Encode_Decode import encode_decode
from threading import Thread
#-------------------------------------------------------------------------------------------#
class EchoClient(Protocol):
def connectionMade(self):
print "Sending inital hello request"
ed = encode_decode()
to_send = ed.encode("hello",1,["client"])
# Sending a callback signal to the GUI
wx.CallAfter(pub.sendMessage, 'action', arg1=to_send, arg2="NULL")
self.transport.write(to_send)
def dataReceived(self, data):
ed = encode_decode()
status,count,item = ed.decode(data)
# Need to see what is contained in the message by seeing what status is
if status == "url":
print "Status is %s...Count is %s... Full message is %s" % (status,str(count),data)
wx.CallAfter(pub.sendMessage,'sendRequest',arg1=self.sendAccessRequest)
# Calling the pub.SendMessage event to alert the listener and take the information
wx.CallAfter(pub.sendMessage, 'update_url', arg1=item)
elif status == 'hello' and item == 'server':
to_send = ed.encode("ping",1,['client'])
self.transport.write(to_send)
wx.CallAfter(pub.sendMessage,'sendRequest',arg1=self.sendAccessRequest)
time.sleep( 2 )
def sendAccessRequest(self,request):
ed = encode_decode()
rtn = ed.encode('service','1',request)
self.transport.write(rtn)
#-------------------------------------------------------------------------------------------#
class EchoClientFactory(ClientFactory):
protocol = EchoClient
def clientConnectionFailed(self, connector, reason):
print "Connection failed - goodbye!"
reactor.stop()
def clientConnectionLost(self, connector, reason):
print "Connection lost - goodbye!"
reactor.stop()
#-------------------------------------------------------------------------------------------#
class CtxFactory(ssl.ClientContextFactory):
def getContext(self):
self.method = SSL.SSLv23_METHOD
ctx = ssl.ClientContextFactory.getContext(self)
ctx.use_certificate_file('./cert.pem')
ctx.use_privatekey_file('./key.pem')
return ctx
#-------------------------------------------------------------------------------------------#
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
# begin wxGlade: MyFrame.__init__
kwds["style"] = wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.frame_1_statusbar = self.CreateStatusBar(1, 0)
self.combo_box_1 = wx.ComboBox(self, wx.ID_ANY, choices=[], style=wx.CB_DROPDOWN)
self.combo_box_1.Bind(wx.EVT_COMBOBOX, self.item_selected)
self.text_ctrl_1 = wx.TextCtrl(self, wx.ID_ANY, "")
self.button_1 = wx.Button(self, wx.ID_ANY, _("button_1"))
self.button_1.Bind(wx.EVT_BUTTON, self.button_pressed)
### Going to want to setup all the Pub/Sub stuff here
# Publisher().subscribe(self.updateDisplay, "update")
pub.subscribe(self.do_action,"action")
# Going to connect an event to the list box
pub.subscribe(self.do_update_url,'update_url')
# Goiong to connect the event
pub.subscribe(self.do_sendRequest,'sendRequest')
self.__set_properties()
self.__do_layout()
def __set_properties(self):
# begin wxGlade: MyFrame.__set_properties
self.SetTitle(_("frame_1"))
self.frame_1_statusbar.SetStatusWidths([-1])
# statusbar fields
frame_1_statusbar_fields = [_("status")]
for i in range(len(frame_1_statusbar_fields)):
self.frame_1_statusbar.SetStatusText(frame_1_statusbar_fields[i], i)
def __do_layout(self):
# begin wxGlade: MyFrame.__do_layout
sizer_2 = wx.BoxSizer(wx.VERTICAL)
grid_sizer_1 = wx.GridSizer(1, 2, 0, 0)
sizer_2.Add(self.combo_box_1, 0, wx.EXPAND, 0)
grid_sizer_1.Add(self.text_ctrl_1, 0, wx.ALIGN_RIGHT, 0)
grid_sizer_1.Add(self.button_1, 0, 0, 0)
sizer_2.Add(grid_sizer_1, 1, wx.EXPAND | wx.ALIGN_CENTER_VERTICAL, 0)
self.SetSizer(sizer_2)
sizer_2.Fit(self)
self.Layout()
def button_pressed(self, event):
print "I was pressed???"
print "did the action work?"
# Publisher().sendMessage,"update", recieved
# pub.sendMessage("action",'lalalalala')
# wx.CallAfter(pub.sendMessage, "update", "Did this work, was I recieved??")
print self.text_ctrl_1.GetValue()
wx.CallAfter(pub.sendMessage, 'action', arg1="ListA", arg2="ListB")
self.wthread = WorkerThread(self.text_ctrl_1.GetValue)
self.wthread.dumpFactory()
def item_selected(self, event):
self.sendAccessRequest(self.combo_box_1.GetValue())
# wx.CallAfter(pub.sendMessage,'action',)
def do_action(self,arg1=None,arg2=None):
print "Called from do_action: %s" % (arg1)
def do_update_url(self,arg1=None, arg2=None):
print arg1,arg2
""" Updates the dropdown box """
self.combo_box_1.Clear()
for i in arg1:
self.combo_box_1.Append(i)
def do_sendRequest(self,arg1=None,arg2=None):
""" Will get the method sendAccessRequest from EchoClient to send data back and forth """
self.sendAccessRequest = arg1
#-------------------------------------------------------------------------------------------#
class dump(object):
"""docstring for dump"""
def __init__(self,obj):
for attr in dir(obj):
if hasattr( obj, attr ):
print( "obj.%s = %s" % (attr, getattr(obj, attr)))
#-------------------------------------------------------------------------------------------#
## Threading
class WorkerThread(Thread):
""" Threading Class """
def __init__(self,txtbx):
Thread.__init__(self)
self.txtbx = txtbx
print self.txtbx
self.start() # Start the thread
def run(self):
factory = EchoClientFactory()
reactor.connectSSL('localhost',8000, factory, CtxFactory())
reactor.run(installSignalHandlers=0)
self.factory = factory
self.reactor = reactor
def dumpFactory(self):
dump(reactor)
#-------------------------------------------------------------------------------------------#
# end of class MyFrame
if __name__ == "__main__":
gettext.install("app") # replace with the appropriate catalog name
# app = wx.PySimpleApp(0)
app = wx.App()
# wx.InitAllImageHandlers()
frame_1 = MyFrame(None, wx.ID_ANY, "")
app.SetTopWindow(frame_1)
frame_1.Show()
app.MainLoop()
我确实遇到过类似的情况,我的解决方案是使用一个队列将你的应用程序与线程连接,然后你可以向线程发送消息/命令,并从线程控制你的服务器,收集数据,这有点麻烦,我建议你在Qt反应器上安装Twisted,使用Qt而不是wx,这样,您可以删除线程,使您的应用程序的设计更简单 希望这能有所帮助,,
干杯不幸的是,从我所看到的情况来看,twisted与wx的配合不太好。。。见:。。。(请注意,这并不是说你不能。你只需要实现自己的主循环。你可以使用wxreactor在Twisted下运行wx,并删除线程。下面是一个通过WebSocket发送和接收信息的wx应用示例: