Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have a TCP server and a TCP client.
I want to make a GUI version of the code below, using .
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()
share|improve this question

1 Answer

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.

share|improve this answer
How can I change my socket script to be without the inf loops? – Schoolboy Feb 19 at 11:12
I have updated the answer with an example. But there is a lot more work to be done... – Fenikso Feb 19 at 12:43
Thx... The non-blocking way should be what I need.. But could you just point me to how to do that ?? – Schoolboy Feb 20 at 8:31
But the inf loop is still there. I don't know if I should multi-thread. – Schoolboy Feb 20 at 11:32
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.