-1

I'm playing about with a motion controller, therefore to "click" a button I am finding out which button is closest to the middle at any given point and then using the button.invoke() method.

I am confident the buttons and setup is working, because whenever I click the buttons - they work fine. However, When the button is called via the "button.invoke" method the whole thing just freezes up.

Other information which may be useful: - The gui is being updated in it's own thread through the .mainloop function. - Everything works fine when being clicked by a mouse - The button.invoke() method works fine - when doing a simple print operation. It only freezes when switching frame.

Any help would be great, thanks.

user2498925
  • 1
  • 1
  • 2
  • 4
    Can you share some code to show us a little more of the workings, especially around what's going on inside `button.invoke()`? – Oren Jun 18 '13 at 22:47
  • 1
    Also, is `button.invoke` being called from a different thread than `mainloop`? That's not legal in tkinter; it may work in some cases but not others, or the same case may work sometimes but not always, or it may work on one platform or Tk version but not another, etc.—but if it ever works, it's just because you were getting lucky; it's not supposed to. – abarnert Jun 18 '13 at 23:56
  • I think you have hit the problem on the head there. The problem is thread A is running mainloop(), which just waits for something so it will never leave that line. Thread B invokes the button when using the motion controller. I should really change my question at this point to "How do I only run "Mainloop" for a finite amout of time? Or change something so mainloop would handle the change" – user2498925 Jun 19 '13 at 08:57

1 Answers1

1

Are you saying that mainloop runs in a separate thread from where you create the widgets? If so, that's your problem. You can only ever call tkinter functions from one thread.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • Sorry I should have been more clear. So here's the problem: Thead A - in charge of making the GUI in it's initialisation, and the running "a.mainloop()" This is fine when it detects it's own button clicks. Thread B - controls the motion camera. Because the idea is for them not to use the mouse I use the "closest_button.invoke()" method. However - this means command is started from thread B, because unlike a button click it isn't a change on the gui (not phyical button press, just does the associated command) which thread A then picks up in it's main loop - it is invoking the command. – user2498925 Jun 19 '13 at 09:08
  • @user2498925: you can't run the `invoke` method from another thread. The common solution is for your thread to put something on a thread safe queue, then have the GUI thread poll the queue periodically. There are examples of that on stackoverflow. – Bryan Oakley Jun 19 '13 at 11:21
  • The problem with that however is that the GUI thread, is running the mainloop function. And will not execute any other lines until the GUI dies. – user2498925 Jun 19 '13 at 12:00
  • @user2498925: there's no problen - mainloop is a _loop_ which means it can run things periodically. Use `after` to schedule the queue to be polled a few ms in the future, then have that function re-schedule itself for an infinitely running poll. There are several examples on this site, for example: http://stackoverflow.com/a/2401181/7432 – Bryan Oakley Jun 19 '13 at 12:41