Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将信息从wxPython线程发送到twisted线程_Python_Multithreading_Client_Twisted - Fatal编程技术网

如何将信息从wxPython线程发送到twisted线程

如何将信息从wxPython线程发送到twisted线程,python,multithreading,client,twisted,Python,Multithreading,Client,Twisted,我有一个似乎无法解决的问题。这个问题与我正在构建的wxPython/twisted应用程序有关。此应用程序执行以下功能。当用户单击按钮时,此应用程序将启动gui wxPython窗口。然后启动一个新线程,通过ssl连接到TwistedTCP服务器。此连接是恒定的,在用户运行GUI时将保持连接。从服务器发送到gui客户端的任何数据都会使用wx.lib.pubsub显示在gui中。我所描述的项目工作正常 我的问题是: 我有一个wxPython组合框,它根据从连接到的服务器发送到客户机的数据填充。我有

我有一个似乎无法解决的问题。这个问题与我正在构建的wxPython/twisted应用程序有关。此应用程序执行以下功能。当用户单击按钮时,此应用程序将启动gui wxPython窗口。然后启动一个新线程,通过ssl连接到TwistedTCP服务器。此连接是恒定的,在用户运行GUI时将保持连接。从服务器发送到gui客户端的任何数据都会使用wx.lib.pubsub显示在gui中。我所描述的项目工作正常

我的问题是: 我有一个wxPython组合框,它根据从连接到的服务器发送到客户机的数据填充。我有一个事件,当在组合框中选择某个内容时,该信息(选择)应发送到服务器。我不知道怎么做。我的意思是,我从combobox(self.combo\u box\u 1.GetValue())中选择了值,但不知道如何将该信息发送到运行在不同线程中的twisted reactor中。这简直要了我的命。我已经搜索过如何做到这一点,但不知道如何让它在不同线程中使用一个持续运行的套接字。欢迎提供任何帮助/示例

这是我正在使用的代码

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应用示例: