我有一个似乎无法解决的问题。这个问题与我正在构建的wxPython / twisted应用程序有关。此应用程序预先执行以下功能。该应用程序启动一个gui wxPython窗口,当用户单击该按钮时。然后启动一个新线程,通过ssl连接到Twisted TCP服务器。此连接是常量,并在用户运行GUI时保持连接。从服务器发送到gui客户端的任何数据都显示在使用wx.lib.pubsub的gui中。我描述的项目工作正常。
我的问题: 我有这个wxPython组合框,它从从它连接到的服务器发送到客户端的数据中填充。我有一个事件,当在组合框中选择某些内容时,该信息(选择)应该被发送到服务器。我不知道该怎么做。我的意思是我从组合框中选择了值(self.combo_box_1.GetValue()),但不知道如何将该信息发送到在不同线程中运行的扭曲反应器中。这让我很难过。我已经搜索了如何执行此操作,但不了解如何使其在不同的线程中使用常量运行的套接字。任何帮助/例子都会非常受欢迎。
以下是我正在使用的代码
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()
答案 0 :(得分:0)
我确实有类似的情况,我的解决方案是使用一个将您的应用程序与线程连接的队列然后您可以向线程发送消息/命令,并从线程控制您的服务器收集的数据,这是一个有点喧嚣,我建议你把Twisted放在Qt反应器上并使用Qt代替wx,这样你就可以删除Thread并使你的应用程序更简单!
希望这可以提供帮助, 干杯