How to control when does the console shows in python - python

I am making a python script that shows content in the console for the first 10-20 seconds after executed before the tkinter UI is shown. So is there any lines I can add to control the visibility of the console? .pyw file extension completely disables the console but I need the console to occasionally show up. Any suggestions?

First of all, you need to write your entire Tkinter code under a function.
def main_program():
# root = Tk() ...
Below this you need to write an empty print statement for the console. Below this, you can write anything. But the problem is sometimes, console quickly opens, prints the statement and closes it, so you barely have time to see
So, use time.sleep() -
import time
from tkinter import *
def main():
root = Tk()
root.mainloop()
print('Wait for a second')
time.sleep(1)
main()
This will show the print statement, delay the program for 1 second, and then open Tkinter window.

There are 2 ways to do it.
You can withdraw the window, print whatever you want and at the last, make it visible. .withdraw basically hides the window without any changes to the widgets.
from tkinter import *
root=Tk()
root.withdraw()
print("Hey there! Please wait for 10 seconds for the app to start...")
root.after(10000,lambda: root.deiconify())
root.mainloop()
Or, the second one is
from tkinter import *
import time
def create_window():
root = Tk()
root.mainloop()
print('Hey there! Please wait for 10 seconds for the app to start...')
time.sleep(10)
create_window()

Related

python tkinter showing message without pausing program

I'm trying to write a program with python tkinter.
I wonder if it's possible to show a message or window without pausing the program?
For example, I want to show the status of the program (starting, waiting, finished)
but it seems like when the 'waiting' message/window is displaying, the program won't continue unless I close the window manually.
This is what I have now
from tkinter import *
root = Tk()
root.geometry('200x200')
root.configure(bg='gray92')
root.mainloop()
print(1)
root1 = Tk()
root1.geometry('200x200')
Message(root1, text="waiting...").pack()
root1.mainloop()
print(2)
I had to close the second window to print 2.
Is it possible to print 2 without closing the second window??

Tkinter TopLevel not showing when it's supposed to

I have a very simple python code: a tkitner button that process some images in the background. I wanted to open a tkinter toplevel to show the user that it was doing something, but for my surprise is not working as I thought it would. The command on the tk.Button is the next method:
def processing(self):
"""Starts the images processing"""
# Open a Tk.Toplevel
aux_topLevel = Splash(self.window) # a simple Tk.Toplevel class, that works perfectly
self._process_images() # starts processing the images
# I wanted to kill here the topLevel created before
aux_topLevel.destroy()
My surprise: the window is displayed once the processing images is done (tried it out adding prints and time.sleep), however, i couldn't display the TopLevel when I wanted to.
Is there anything am I doing wrong? Any help is appreciated. Thank you.
Consider the following example and try to run it.
What you'd think should happen is that the new Toplevel window should open, some event happens for a period of time and then the window is destroyed.
What actually happens is the window is opened, but never displayed, the task occurs and then the window is destroyed.
from tkinter import *
import time
def processing():
new = Toplevel(root)
new.geometry("200x150")
lbl = Label(new,text="--")
lbl.grid()
for i in range(50):
time.sleep(0.1)
#Un-comment the line below to fix
#root.update()
print(i)
lbl['text'] = "{}".format(i)
new.destroy()
root = Tk()
root.geometry('200x100')
btnGo = Button(root,text="Go",command=processing)
btnGo.grid()
root.mainloop()
If you un-comment out the root.update() line and re-run the code, the window will be displayed.
There are better ways to deal with tasks that takes a while to process, such as threading.

How to stop waiting for input in tkinter dialog box?

I am currently coding a program that will do something (e.g count numbers constantly) until something is inputted into a dialog box displayed.
However, whenever I try this, the program freezes when waiting for an input and so does not make any progress in the counting process I am trying to run in the background.
Is there any way to have a timer that continuously runs in the background so that in say 5 minutes, the counter instantly stops and the dialog box disappears? This is a basic skeleton of my code. I used the tkinter dialog box for input and tried to create a timer that will run in the background.
from time import *
from tkinter import *
from tkinter import messagebox
from tkinter import simpledialog
while timer<300:
sleep(1)
timer += 1
ROOT = Tk()
ROOT.withdraw()
USER_INP = simpledialog.askstring(title="Code Required",
prompt="What's the Code?:")
Preferably without external modules but if not that is fine. Thanks in advance :)
This is the code requested
from tkinter import *
from tkinter import simpledialog
root = Tk()
root.withdraw()
def ask():
simpledialog.askstring(title="Code Required",
prompt="What's the Code?:")
## root.after(5000, root.destroy()) #added in the root.after() to try and terminate it after set time
root.after(3000,ask) #triggers ask() after 3000 ms(3 seconds)
root.after(100000, root.destroy()) # tried to wait 10 seconds before it breaks but this doesn't show the dialog box any more
root.mainloop()
Here is a basic code with tkinter that makes the dialogbox pop up after 5 seconds.
from tkinter import *
from tkinter import simpledialog
root = Tk()
root.withdraw()
def ask():
simpledialog.askstring(title="Code Required",
prompt="What's the Code?:")
root.after(5000, root.destroy) #added in the root.after() to try and terminate it after set time
root.after(3000,ask) #triggers ask() after 3000 ms(3 seconds)
#root.after(10000, root.destroy) # tried to wait 10 seconds before it breaks but this doesn't show the dialog box any more
root.mainloop()
Here after() triggers a function after the given time, i.e, 3000 ms(3 sec), so you can adjust the timer, out there too. This is just an example and you can edit this more as you like.
Why use after() and not while and a timer?
This is because a while loop interferes a tkinter mainloop() causing the window to be unresponsive, so it is not recommended to use while or time.sleep(). Instead you could use the built-in after() method by tkinter or threading too.
Here is a bit more on after():
It takes two positional arguments,mainly, ms and func
ms - It is the time(in milliseconds) after which the specified function will be triggered.
func - It is the function to be triggered after the specified ms finises.
WARNING:
Keep in mind that the root window is not destroyed, its just hidden, so as long as the root window is not destroyed, the program keeps on running in the background, so you will have to bring back the window and close it for the task to end. For this reason, ive added root.destroy() there.
Take a look here for a bit more understanding on after()
Hope it cleared your doubts, do let me know if any errors.
Cheers

Change text on tkinter button during call back execution

I'm trying to change the text on a button when the call back of that particular button executing.
Let's say I have "Run" as the text on my button, and I want to change it to "Running" just after it has been clicked, and during the call back execution.
After the completion of call back execution, I want to change it back to "Run".
I am not getting which part of my code is buggy.
import Tkinter as tk
import time
root = tk.Tk()
def change():
button.config(text='Running')
button.config(state='disabled')
print "start"
time.sleep(5)
print "end"
button.config(state='normal')
button.config(text="Run")
button = tk.Button(root,text="Run",command=change)
button.pack()
root.mainloop()
Sleep makes the WHOLE program stop for a moment, including the interface, usually stopping it from changing the interface itself, due to how the mainloop works.
Here, try the .after function, this should work fine.
import Tkinter as tk
import time
root = tk.Tk()
def change():
button.config(text='Running')
button.config(state='disabled')
print "start"
root.after(5000,changeback)
def changeback():
print "end"
button.config(state='normal')
button.config(text="Run")
button = tk.Button(root,text="Run",command=change)
button.pack()
root.mainloop()
root.after(5000,changeback) will call a command after 5000 milliseconds, or 5 seconds without stopping the whole program, that being changeback()

label.configure works sometimes why?

Part of my code is as follows:
def get_songs():
label6.configure(text='Wait')
os.system('/home/norman/my-startups/grabsongs')
label6.configure(text='Done')
The label is not updated at the first .configure() but is at the second one.
Except if I cause a deliberate error immediately after the first one at which point it is updated and then the program terminates.
The system call takes about 2 minutes to complete so it isn't as if there isn't time to display the first one.
I am using Python 2.7.6
Does anyone know why please?
I'm going to guess you're using Tkinter. If so, as #albert just suggested, you'll want to call label.update_idletasks() or label.update() to tell Tkinter to refresh the display.
As a very crude example to reproduce your problem, let's make a program that will:
Wait 1 second
Do something (sleep for 2 seconds) and update the text to "wait"
Display "done" afterwards
For example:
import Tkinter as tk
import time
root = tk.Tk()
label = tk.Label(root, text='Not waiting yet')
label.pack()
def do_stuff():
label.configure(text='Wait')
time.sleep(2)
label.configure(text='Done')
label.after(1000, do_stuff)
tk.mainloop()
Notice that "Wait" will never be displayed.
To fix that, let's call update_idletasks() after initially setting the text:
import Tkinter as tk
import time
root = tk.Tk()
label = tk.Label(root, text='Not waiting yet')
label.pack()
def do_stuff():
label.configure(text='Wait')
label.update_idletasks()
time.sleep(2)
label.configure(text='Done')
label.after(1000, do_stuff)
tk.mainloop()
As far as why this happens, it actually is because Tkinter doesn't have time to update the label.
Calling configure doesn't automatically force a refresh of the display, it just queues one the next time things are idle. Because you immediately call something that will halt execution of the mainloop (calling an executable and forcing python to halt until it finishes), Tkinter never gets a chance to process the changes to the label.
Notice that while the gui displays "Wait" (while your process/sleep is running) it won't respond to resizing, etc. Python has halted execution until the other process finishes running.
To get around this, consider using subprocess.Popen (or something similar) instead of os.system. You'll then need to perodically poll the returned pipe to see if the subprocess has finished.
As an example (I'm also moving this into a class to keep the scoping from getting excessively confusing):
import Tkinter as tk
import subprocess
class Application(object):
def __init__(self, parent):
self.parent = parent
self.label = tk.Label(parent, text='Not waiting yet')
self.label.pack()
self.parent.after(1000, self.do_stuff)
def do_stuff(self):
self.label.configure(text='Wait')
self._pipe = subprocess.Popen(['/bin/sleep', '2'])
self.poll()
def poll(self):
if self._pipe.poll() is None:
self.label.after(100, self.poll)
else:
self.label.configure(text='Done')
root = tk.Tk()
app = Application(root)
tk.mainloop()
The key difference here is that we can resize/move/interact with the window while we're waiting for the external process to finish. Also note that we never needed to call update_idletasks/update, as Tkinter now does have idle time to update the display.

Categories

Resources