Waiting for screen and message input at the same time

I have retired and tried to get my head around Python (as you can probably tell from the code!) And I am trying to program a simple game with a laptop and tablet (both run Python 3.3.5 under Windows 8).
My problem in a nutshell: I have two simple working programs (below): one waits for a button press and changes the screen color, the other waits for a message from the comm client and changes the screen color.
What's the easiest way to combine them into one running program, so we're waiting for screen activity or comms to appear in any order?
I've tried various ways I've found on this site and others around threads and waits, but none seems perfect. Any help would be appreciated!

# PROGRAM 1 - wait for user to click button
from tkinter import *
win1 = Tk()
win1.attributes('-fullscreen', True)

def turnorange():
    win1.configure(bg='orange')
def turnwhite():
    win1.configure(bg='white')

btn1 = Button( win1 , text='Click for orange' , command=turnorange)
btn1.place(x=100,y=100)
btn2 = Button( win1 , text='Click for white' , command=turnwhite)
btn2.place(x=250,y=100)
btn_end = Button( win1 , text='Close' , command=exit)
btn_end.place(x=200,y=200)
win1.mainloop()

# PROGRAM 2 - wait for message from client
from tkinter import *
import socket
win1 = Tk()
win1.attributes('-fullscreen', True)

def changecolour(col): 
    win1.configure(bg=col)
    win1.update()

def startup():
    ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    ss.bind((socket.gethostname(), 8089))
    ss.listen(5)
    while True:
        conn, address = ss.accept()
        colour = conn.recv(64).decode()
        if len(colour) > 0:
            changecolour(colour)
            data = 'whatever'
            conn.send(data.encode())

btn = Button( win1 , text='Click to listen' , command=startup)
btn.place(x=100,y=100)
win1.mainloop()

      

+3


source to share


2 answers


The problem with your current code is that startup is blocking; you need to find a way to poll for new connections so that mainloop can watch for other events.

Try the socket tutorial to get a grasp of the basics and this question for some of the specifics of using non-blocking sockets.



To check your socket check code periodically, check tk after .

+1


source


These links gave me a good idea of ​​what was going on and I solved the problem now.

Program 3 combines programs 1 and 2 and works on my laptop. Program 4 runs on a Windows tablet. In program 3, if we press btn1 or btn2, it is processed only once when we have a tablet connection, so the tablet just needs to send a regular message, say every 0.2 seconds: "A" to change the color to blue otherwise it falls back to cornsilk.



It works, so I'm happy. I would be even happier if I could figure out how it breaks out of the while loop to handle events!

from tkinter import *
# PROGRAM 3 on LAPTOP: wait for message from tablet OR for user to click button
import socket
win1 = Tk()
win1.attributes('-fullscreen', True)

def turnorange():
    changecolour('orange')
def turnyellow():
    changecolour('yellow')

def changecolour(col): 
    win1.configure(bg=col)
    win1.update()

def startup():
    ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    ss.bind((socket.gethostname(), 8089))
    ss.listen(5)

    while True:
        conn, address = ss.accept()
        colour = conn.recv(64).decode()
        if len(buf) > 0:
            if buf == "A":
                changecolour('cyan')
            else:
                changecolour('cornsilk')
        data = 'whatever'
        conn.send(data.encode())

btn = Button( win1 , text='Click to listen' , command=startup)
btn.place(x=100,y=100)

btn1 = Button( win1 , text='Click for orange' , command=turnorange)
btn1.place(x=300,y=100)
btn2 = Button( win1 , text='Click for yellow' , command=turnyellow)
btn2.place(x=400,y=100)

win1.mainloop()


# PROGRAM 4 on TABLET: sends message to laptop (a) when button clicked, and (b) every 0.2 seconds
from tkinter import *
import socket

win1 = Tk()
win1.attributes('-fullscreen', True)

def sendstuff(data):
    cs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    cs.connect(('192.168.1.7', 8089))
    cs.sendall(data.encode())
    buf = cs.recv(64).decode()
    cs.close()

def clicked():
    sendstuff("A")

def sendroutine():
    sendstuff("X")
    win1.after(200, sendroutine) # time delay, 1000 =1 sec during test, 200 = 0.2 secs when live

btn1 = Button( win1 , text='Start' , command=sendroutine, width = 20, height = 3)
btn1.place(x=200,y=200)
btn2 = Button( win1 , text='Click for cyan' , command=clicked, width = 20, height = 3)
btn2.place(x=400,y=200)

win1.mainloop()

      

0


source







All Articles