I am writing a python app using Tkinter for buttons and graphics and having trouble getting a timer working, what I need is a sample app that has three buttons and a label.
[start timer] [stop timer] [quit]
When I press the start button a function allows the label to count up from zero every 5 seconds, the stop button stops the timer and the quit button quits the app.
I need to be able to press stop timer and quit at any time, and the time.sleep(5) function locks everything up so I can't use that.
currently i'm using threading.timer(5,do_count_function) and getting nowhere !
I'm a vb.net programmer, so python is a bit new to me, but hey, i'm trying.
Check the .after method of your Tk() object. This allows you to use Tk's timer to fire events within the gui's own loop by giving it a length of time and a callback method.
Related
I've got an interface where there is a 'Start' button. It runs a 'main' command where it starts a loop to run some measurements on a powermeter. I want to be able to click on an 'OK' button every time the measure is ready to be done. This button would replace the 'Start' button.
But when I try to destroy the button (buttonStart.destroy()) and then run the command main()
, the command executes but doesn't delete the button until the very end.
I've tried using threads from threading package, but it doesn't really work.
If there is a way to both destroy the button and run a command, I would be very interested !
Thanks a lot
The event loop must be given the opportunity to process events in order for the window to be removed from the screen.
There are a couple of ways to make that happen. The first is to call the update_idletasks method on any widget. That is usually enough to process the event related to the destruction of the widget, though it may be necessary to call update instead. Calling update should be avoided if at all possible. My rule of thumb is to start with update_idletasks. If that doesn't work, switch to update or switch to using after.
def my_custom_function():
startButton.destroy()
root.upddate_idletasks()
main()
The second method is to run your main function via after or after_idle. This will let tkinter naturally process all pending events before starting main. I would argue that this is the best approach. I recommend trying after_idle first, and if that doesn't work, switch to after with a small delay.
def my_custom_function():
startButton.destroy()
root.after_idle(main)
I am trying to write a function that launches a popup in a kivy gui based on a conditional. The method is outside of the main app because I am using multithreading to have both run at the same time. Every time I try to initialize a new popup in the method which is outside of the main app, it crashes. If I don't initialize it, it runs fine. Any ideas?
You must perform GUI related operations (like opening or dismissing a Popup) on the kivy thread.
In your code, where you would call sm.open_unrecognized() do Clock.schedule_once(sm.open_unrecognized, 0). This will schedule the call to open_unrecognized on the kivy thread after the next frame is displayed.
Dismissing the Popup can be done automatically (any click outside the Popup) or explicitly using something like a Button in the Popup. Note that any code called by a Button event is performed on the kivy thread.
See the Clock documentation for more information
So I was wondering if someone would be able to help shed a little light for me on something I am working on in Python.
I am creating a program with a Tkinter GUI interface that interacts with a Serial device, and an ADC chip to measure voltage. I want to make sure I properly understand how I'm building the main program loop to keep everything running smoothly. I'm going to lay out how I think the program should run, if anyone has any corrections please throw them at me.
Program is run, GUI Interface initializes
User presses a button
send signal of button through serial
measure/display voltage levels
periodically update voltage display
if button is pressed, return to step 3
Now I know to run my Tkinter GUI I set up mainloop() as the last line of code. Now my question is simply, is that all I will need? Will mainloop() continually update while it waits for another button press, or will I essentially have to creatre an update method that cycles through everything until another button is pressed?
Will mainloop() continually update while it waits for another button press, or will I essentially have to creatre an update method that cycles through everything until another button is pressed?
Not all. That's why you are using tk.Tk().mainloop(). tkinter does this for you. All you are expected to do is implement the functionality that should happen when your button is pressed. tkinter will listen for the button press.
I am building an app that, when the user hits a 'run' button, generates a table of buttons.
Because this process takes a while, I want to add a popup or progress bar to alert the user that the function is running and not frozen. To do this I decided to create a popup and call my function using threading so that the screen will be updated when the function starts (as opposed to once it is done).
mythread = threading.Thread(target=run_function)
mythread.start()
The trouble is that when I call my function from the above code it works very strangely: the columns of my table are the wrong width, some of my buttons are arbitrarily empty, and others have the wrong fill color. To fix this, all I need to do is to remove the threading operation and simply call run_function()
Any idea why this is happening?
I am new to Python, so it is likely some dumb mistake, but I have no idea. What is different between a process running as a thread and its default operation?
Disclaimer: I haven't worked with Kivy.
Not every framework works well with multithreading.
But most of the GUI frameworks have an event loop which is responsible for managing user events (mouse clicks, keyboard) and queued drawing operations (widgets).
In your case if don't want the UI to be freezed, you should regularly give control to your framework's event loop.
I guess kivy.base.EventLoopBase.dispatch_input is what you need to call to show an added widget or to handle user events.
Tkinter method "deiconify" seems not working on ubuntu(12.04, unity), but the the following code works as expected on windows 7. I need to show the window even it is minimized when something happens in another project https://github.com/thinker3/youdao.
from time import sleep
from Tkinter import Tk
class GUI():
def __init__(self):
self.root = Tk()
self.root.title("Test")
self.root.protocol("WM_DELETE_WINDOW", self.close_handler)
self.root.mainloop()
def close_handler(self):
self.root.iconify()
sleep(1)
self.root.deiconify()
if __name__ == '__main__':
gui = GUI()
What you are seeing is apparently the difference between Windows and non-Windows. It looks to me like the Windows behavior is a bug. At the very least, it's not expected behavior. What you are seeing on ubuntu is what I would expect to see.
For a GUI to do anything, the event loop must be running. Everything that happens is the response to an event. The drawing of a window on the screen is a response to an event. A button click is a response to an event. The visual effect of a button being pressed is a response to an event. And so on.
When you call iconify, that causes an event to be sent to the app saying "remove the window from the screen". The event loop sees the event, and redraws (or "un"draws) the window. The reverse happens when you call deiconify -- the system gets a redraw event, and tkinter redraws the window on the screen.
In your code, you never give the event loop a chance to respond to these events. You ask it to iconfiy, then you sleep, then you deiconify, all without giving the event loop a chance to respond. While the sleep command is running no events are processed. So, when you wake from sleep, the system hides the window, and then microseconds later it redraws it.
What is probably happening on windows is that the window manager is getting the iconfiy command and removing the window without tkinter's involvement. In other words, tkinter doesn't actually do anything to make it go away. On X11-based systems, however, this is all managed by the event loop.
If you want the window to go away, and a second later reappear, use the event loop to your advantage. Allow the event loop to update the screen, and arrange for the deiconify to happen at sometime in the future. For example:
def close_handler(self):
self.root.iconify()
self.after(1000, self.root.deiconify)
This should work on all platforms. It allows the event loop to respond to the iconify event, and then a second later the deiconify command will run.