2013-02-19 41 views
2

我有一個TCP服務器和一個TCP客戶端。
我想使用製作下面的代碼的GUI版本。
我準備好了GUI界面腳本,但是,我在合併這兩個腳本時遇到了問題。使用套接字與wxpython

如何合併我的套接字腳本和我的GUI?

我的socket服務器

from socket import * 
from time import ctime 
import random 

bufsiz = 1024 
port = random.randint(1025,36000) 
host = 'localhost' 
addr = (host, port) 
print 'Port:',port 

tcpServer = socket(AF_INET , SOCK_STREAM) 
tcpServer.bind(addr) 
tcpServer.listen(5) 
try: 
    while True: 
     print 'Waiting for connection..' 
     tcpClient, caddr = tcpServer.accept() 
     print 'Connected To',caddr 

     while True: 
      data = tcpClient.recv(bufsiz) 
      if not data: 
       break 
      tcpClient.send('[%s]\nData\n%s' % (ctime(),data)) 
      print data 
     tcpClient.close() 

except KeyboardInterrupt: 
    tcpServer.close() 

raw_input('Enter to Quit') 

我的GUI腳本(由使用w​​xglade)

#!/usr/bin/env python 
# -*- coding: iso-8859-15 -*- 
# generated by wxGlade 0.6.5 (standalone edition) on Mon Feb 18 19:50:59 2013 

import wx 

# begin wxGlade: extracode 
# end wxGlade 


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.chat_log = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE | wx.TE_READONLY) 
     self.text_send = wx.TextCtrl(self, -1, "") 

     self.__set_properties() 
     self.__do_layout() 

     self.Bind(wx.EVT_TEXT_ENTER, self.text_e, self.text_send) 
     # end wxGlade 

    def __set_properties(self): 
     # begin wxGlade: MyFrame.__set_properties 
     self.SetTitle("frame_1") 
     self.SetSize((653, 467)) 
     self.chat_log.SetMinSize((635, 400)) 
     self.text_send.SetMinSize((635, -1)) 
     self.text_send.SetFocus() 
     # end wxGlade 

    def __do_layout(self): 
     # begin wxGlade: MyFrame.__do_layout 
     sizer_1 = wx.FlexGridSizer(1, 1, 1, 1) 
     sizer_1.Add(self.chat_log, 0, 0, 0) 
     sizer_1.Add(self.text_send, 0, wx.ALL, 1) 
     self.SetSizer(sizer_1) 
     self.Layout() 
     # end wxGlade 

    def text_e(self, event): # wxGlade: MyFrame.<event_handler> 
     text = self.text_send.GetValue() 
     self.chat_log.AppendText("\n"+text) 
     self.text_send.SetValue("") 
     event.Skip() 

# end of class MyFrame 

class MyMenuBar(wx.MenuBar): 
    def __init__(self, *args, **kwds): 
     # begin wxGlade: MyMenuBar.__init__ 
     wx.MenuBar.__init__(self, *args, **kwds) 
     self.File = wx.Menu() 
     self.Append(self.File, "File") 
     self.View = wx.Menu() 
     self.Append(self.View, "View") 

     self.__set_properties() 
     self.__do_layout() 
     # end wxGlade 

    def __set_properties(self): 
     # begin wxGlade: MyMenuBar.__set_properties 
     pass 
     # end wxGlade 

    def __do_layout(self): 
     # begin wxGlade: MyMenuBar.__do_layout 
     pass 
     # end wxGlade 

# end of class MyMenuBar 
if __name__ == "__main__": 
    app = wx.PySimpleApp(0) 
    wx.InitAllImageHandlers() 
    frame_1 = MyFrame(None, -1, "") 
    app.SetTopWindow(frame_1) 
    frame_1.Show() 
    app.MainLoop() 

回答

2

一言以蔽之:封裝第一個腳本到一個函數。將你的函數導入wxPython應用程序。從某個事件處理函數調用該函數。將您的功能響應回傳給GUI。

但是,您需要重新設計軟件,使其不包含無限循環。事件處理程序只應該在短時間內運行。另一種方法是在一個單獨的線程中運行你的函數,通過GUI傳遞響應並添加從主GUI線程中終止線程的能力。

這些方針的東西:

import wx 
from socket import * 
from time import ctime 
import random 
import threading 

bufsiz = 1024 
port = random.randint(1025,36000) 
host = 'localhost' 
addr = (host, port) 

class MainWindow(wx.Frame): 
    def __init__(self, *args, **kwargs): 
     wx.Frame.__init__(self, *args, **kwargs) 

     self.panel = wx.Panel(self) 
     self.text = wx.TextCtrl(self.panel, style=wx.TE_MULTILINE) 

     self.sizer = wx.BoxSizer() 
     self.sizer.Add(self.text, 1, wx.ALL | wx.EXPAND, 5) 

     self.panel.SetSizerAndFit(self.sizer) 
     self.Show() 

     self.thread = threading.Thread(target=self.Server) 
     self.thread.start() 

    def Print(self, text): 
     wx.CallAfter(self.text.AppendText, text + "\n") 

    def Server(self): 
     self.Print("Port: {}".format(port)) 

     tcpServer = socket(AF_INET , SOCK_STREAM) 
     tcpServer.bind(addr) 
     tcpServer.listen(5) 
     try: 
      while True: 
       self.Print("Waiting for connection...") 
       tcpClient, caddr = tcpServer.accept() 
       self.Print("Connected To {}".format(caddr)) 

       while True: 
        data = tcpClient.recv(bufsiz) 
        if not data: 
         break 
        tcpClient.send('[%s]\nData\n%s' % (ctime(), data)) 
        self.Print(data) 
       tcpClient.close() 

     except KeyboardInterrupt: 
      tcpServer.close() 

app = wx.App(False) 
win = MainWindow(None) 
app.MainLoop() 

然而,這並不在退出時終止另一個線程。 tcpServer.accept()正在阻止操作。你可能想看看這個answer如何以非阻塞的方式連接到套接字。然後,您將能夠輕鬆地使用某些共享標誌的終端來終止您的線程。

+0

如何將我的套接字腳本更改爲沒有inf循環? – pradyunsg 2013-02-19 11:12:46

+0

我已經用一個例子更新了答案。但是還有很多工作要做... – Fenikso 2013-02-19 12:43:51

+0

Thx ...非阻塞的方式應該是我所需要的..但​​是,你能指點我怎麼做? – pradyunsg 2013-02-20 08:31:27