Reputation: 19456
I have a TCP server and a TCP client.
I want to make a GUI version of the code below, using wxpython.
I have the GUI interface script ready, but, I am having problems merging the two scripts.
How do I merge my socket script(s) and my GUI?
My socket server
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')
My GUI script (made using wxglade)
#!/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()
Upvotes: 2
Views: 2316
Reputation: 9451
In a nutshell: Encapsulate your first script into a function. Import your function into the wxPython app. Call the function from some event handler. Communicate back your function response to the GUI.
However, you would need to redesign your software so it does not contain infinite loop. Event handlers should run for short time only. Another way would be to run your function in a separate thread, communicate the response with GUI and add ability to terminate the thread from your main GUI thread.
Something along these lines:
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()
This however does not terminate another thread upon exit. tcpServer.accept()
is blocking operation. You may want to look into this answer how to connect to socket in a non-blocking way. Then you would be able to easily terminate your thread using some kins of shared flag.
Upvotes: 2