Reputation: 720
I'm trying to make an infinite loop (with a break) that runs alongside my Tkinter window and interacts with widgets on it. Yes, I have done my research, but when I run my code and activate the function the window stops responding.
I've deleted the 'while true' from the method, and at the end of it placed:
if self.connected:
root.after(100, self.listenServer(id, req))
I think the problem is that the function takes a little while to complete (I'm making an Omegle client, so it has to connect to the server). I can tell that it runs six times, because I put a print statement in the method.
Is there a simple (AKA no threading) method to solve this problem?
Well, if threading is the only way to do it, then I guess it would be fine
Here are my connect and listen methods:
def listenServer(self, id, req):
site = url.urlopen(req)
#We read the HTTP output to get what's going on
rec = site.read()
if 'waiting' in rec:
self.chatbox.config(state=NORMAL)
self.chatbox.insert(END, "Waiting...\n", "italic")
self.chatbox.config(state=DISABLED)
elif 'connected' in rec:
self.chatbox.config(state=NORMAL)
self.chatbox.insert(END, "Stranger connected\n", "italic")
self.chatbox.config(state=DISABLED)
elif 'strangerDisconnected' in rec:
self.chatbox.config(state=NORMAL)
self.chatbox.insert(END, "Stranger Disconnected\n", "italic")
self.chatbox.config(state=DISABLED)
self.connected = False
elif 'typing' in rec:
self.chatbox.config(state=NORMAL)
self.chatbox.insert(END, "Stranger is typing\n", "italic")
self.chatbox.config(state=DISABLED)
elif 'gotMessage' in rec:
self.chatbox.config(state=NORMAL)
self.chatbox.insert(END, "Stranger: " + rec[17:len(rec) - 3] + "\n")
self.chatbox.config(state=DISABLED)
def OmegleConnect(self):
self.chatbox.config(state=NORMAL)
self.chatbox.insert(END, "Connecting...\n", "italic")
self.chatbox.config(state=DISABLED)
site = url.urlopen('http://omegle.com/start', '')
id = site.read()
id = id[1:len(id) - 1]
self.chatbox.config(state=NORMAL)
self.chatbox.insert(END, "Stranger ID: " + id + "\n", "title")
self.chatbox.config(state=DISABLED)
req = url.Request('http://omegle.com/events', urllib.urlencode({'id':id}))
self.chatbox.config(state=NORMAL)
self.chatbox.insert(END, "Finding a stranger...\n", "italic")
self.chatbox.config(state=DISABLED)
self.connected = True
root.after(100, self.listenServer(id, req))
Yes, I know this is quite inefficient with the way it writes to the text widget. I tried making a method to do it more easily, but it wasn't working. I'll worry about that once I get this up and running.
Upvotes: 1
Views: 395
Reputation: 14853
if you do not want to use threading:
tkinterwidget.update() # repaint & use events
or if you want to schedule something:
class MainWindo(Tk):
...
def method(self):
# do something here for every 100 ms
if loop:
self.after(100, self.method)
Be careful not to interact with Tkinter from two threads. My Programs sometimes crashed because of this.
Upvotes: 0
Reputation: 88977
The issue here is that the window needs to be continuously updating in order for the window to react to input - that's a reality of the way the program works, and makes sense.
On the other hand, you want to do something in a loop which doesn't allow the window to update - given this, there is no way for the window to react.
So no, there is no solution to this that won't involve threading or multiprocessing in some way - you need to do two things at once.
If you don't want to deal with threading directly, you could use a library like twisted
to provide the networking you are talking about, which will avoid you waiting on your request to complete.
The other main option is to use the multiprocessing
module or threading
module to move the things you want to do simultaneously to updating your interface into a new thread/process.
Upvotes: 2