2

So I have written a program which has the purpose of recieving values from Tkinter GUI and then sending them to another computer from socket.

Problem is that Tkinter hogs all the loop. I've tried using root.after() but the socket stuff relies on the .get() function, so when called upon since the GUI hasn't appeared yet, there isn't any values for what I'm trying to send.

Here's a more simple code example of what I'm trying to do (mine is much larger, well about 10 different variables larger)

HOST= 'ip address'
PORT = 8000
s= socket(AF_INET, SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1) #I'm aiming for this to eventually be 24.
conn, addr = s.accept

def data():
    Value = str(value.get())
    conn.sendall(str(Value))

root = Tk()
value = Scale(root, from_=255, to=0)
value.set(60)
value.pack() #not using pack but grid. Pack is just easier for simple example.

root.after(500, data())
root.mainloop()

So how do I have this all running in the loop? So it sends the data as the changes are made? (hopefully every second, is what I'm aiming for). I understand the issue with having root.after before root.mainloop, but it won't work otherwise. Mind you, it doesn't work the other way anyway.

I'm thinking thread and queue might be the only solution but I have always struggled with those modules.

I need it to constantly loop both program components to constantly send the data as the GUI slides change.

Davey Boy
  • 79
  • 1
  • 10
  • 1
    Possible duplicate of [How do you run your own code alongside Tkinter's event loop?](http://stackoverflow.com/questions/459083/how-do-you-run-your-own-code-alongside-tkinters-event-loop) – msw Sep 10 '16 at 06:02
  • Nicely presented. The bit that you are missing from the duplicate question is having `data()` reschedule itself at function end. – msw Sep 10 '16 at 06:04
  • Not a duplicate since the other one only uses tkinter and then gets out of it for the rest of the program. I actually got the after function from there. I need constant updating. – Davey Boy Sep 10 '16 at 06:25
  • Msw, what do you mean by data reschedule itself? I don't think I've done that and it could be what's affecting it? – Davey Boy Sep 10 '16 at 06:25
  • Look again at the [first answer to the duplicate question](http://stackoverflow.com/a/459131/282912) at the line commented with `# reschedule event in 2 seconds`. That's what you are missing. Also, the first answer does not "get out of the way" (although a lower rated answer does). – msw Sep 10 '16 at 16:07

1 Answers1

0

Your root problem is that root.after(500, data()) schedules tk to call the result of calling data, which is None. You should pass the function instead: root.after(500, data). To send periodically, add the same line to the end of data, after the conn.sendall call. To only send when the value has changed, you need to store the 'old' value and compare. These changes are incorporated in the following.

from tkinter import *

oldvalue = 60
interval = 500

def data():
    global oldvalue
    newvalue = str(value.get())
    if newvalue != oldvalue:
        print(newvalue)
        oldvalue = newvalue
    root.after(interval, data)

root = Tk()
value = Scale(root, from_=255, to=0)
value.set(oldvalue)
value.pack() #not using pack but grid. Pack is just easier for simple example.

root.after(1, data)
root.mainloop()

Note that using print as a stand-in for send makes experimenting with the GUI much easier. Doing so shows that intermediate values will be sent while moving the slider. If this is not what you want, you will to experiment more. Instead of using after, bind '<ButtonRelease-1>' todata`. Or poll and only send when getting the same value twice. Or whatever.

Terry Jan Reedy
  • 18,414
  • 3
  • 40
  • 52