I created a .py script that autofill some forms using Selenium. In the start of the code, I used Tkinter extension to use the messagebox and filedialog function.
My code runs fine, but everytime I got an annoying window called "tk" (I guess it is related to Tkinter). This window is blank, but I would like to remove it from my code run.
Is there a way to do this?
Try this:
import tkinter as tk
from tkinter import filedialog
# Create a dummy window
root = tk.Tk()
# Hide the window
root.withdraw()
# Use `filedialog` freely
print(filedialog.askopenfilename())
# If you want to destroy the window at the end.
# You don't have to
root.destroy()
The reason why that window appears is linked to how tkinter handles new windows. It uses tkinter.Toplevel instead of a tkinter.Tk. But a tkinter.Toplevel can't exist without a tkinter.Tk so it creates one. That is the window that you see.
To hide the window you have to first create your own tkinter.Tk and hide it using <tkinter.Tk>.withdraw().
Related
I am learning about Tkinter and was wondering if it would cause errors if I did the following:
import tkinter as tk #import modules
from tkinter import ttk
parent=tk.Tk() #create first instance
card1="k spades"
card2="k diamonds"
comboform=ttk.Combobox(parent,textvariable='form',values=[card1,card2,"both","neither"])#create combobox input form
comboform.grid(row=0,column=0)#added to grid
parent.geometry("200x200")
parent.mainloop()#displays tkinter window
#window exited
parent=tk.Tk()#new instance created
label=tk.Label(parent,text="hi")#label produced
label.pack()#added to window
parent.mainloop()
If I click the exit cross is that the same as parent.destroy(); is that good practice? I know you're only supposed to run mainloop() once and have one Tk() instance but if it's destroyed is it going to cause problems? It's not like I'm creating a class the produces a Tk() instance, where there's a risk of multiple instances existing at once.
I am hoping to, eventually, have an application running in the IDLE and then have a tkinter window appear, presenting an input widget of some kind. After the user gives their input, the window would close and the user would continue in the main window. But could I then do it again, opening new windows (like the above code) on the provision that the instance of Tk() is destroyed each time?
If you've destroyed the root window and then create a new one, that's perfectly fine.
The problem with creating multiple instances of Tk is that most people don't understand what that actually does. Having multiple instances of Tk is fine as long as you realize that they operate in completely memory spaces and widgets and bindings in one can't interact with widgets and bindings in the other.
All of that being said, the best practice is to create a single root window at the start of the program, and it stays alive until the program exits. If you need additional windows, the best practice is to create instances of Toplevel.
I have made a GUI using Tkinter for my Python script for a Voice Assistant. It is working pretty well. But I want to add an animation window to display an animation that I have created using After Effects as an intro to the app. I want it to open without the default close(x), maximize and minimize buttons. The window should stay till the animation is completed, and then it would disappear. The main window would then open normally to launch the GUI. To disable the close, maximize and minimize buttons I have used the root.overrideredirect(True) method. But I am not being able to simultaneously open the two windows one after the other as mentioned. I would be highly obliged if somebody would help me out with this! I have tested it with a code on a simple GUI. I am providing the code below for help with the problem!
from tkinter import *
import time
root = Tk()
root.geometry('500x300')
root.overrideredirect(True) # To disable the default Window decoration
time.sleep(5) # Assuming that the animation runs for 5 seconds
root.destroy() # This window destroys after being on screen for 5 seconds
root.mainloop()
root2 = Tk() # After the previous window is destroyed, this window opens up. Assume that this is the main window
root2.geometry('500x300')
root.mainloop()
Please help me out!
The thing you call "animation window" is actually called "splash". There is a way to do what you want. You need to create a root window for the app (a Tk instance), and then you should hide (root.withdraw()) it. Now create a Toplevel for the splash, wait for 5 seconds, destroy it, and show (root.deiconify()) the Tk window again.
Note: time.sleep(5) should never be used with Tkinter, use root.after(ms, func) instead.
from tkinter import *
def show_splash():
splash = Toplevel()
splash.geometry('500x300')
splash.overrideredirect(True) # To disable the default Window decoration
splash.after(5000, splash.destroy) # This window destroys after being on screen for 5 seconds
splash.wait_window()
root = Tk()
root.withdraw()
show_splash()
root.deiconify()
root.mainloop()
PS: Procedural programming is not a good idea for pretty complex Tkinter-based apps. You should consider using OOP instead.
PPS: Take a look at this and this answers.
I made a GUI with Tkinter in python 3. Is it possible to close the window and have the application stays in the Windows System Tray?
Is there any lib or command within Tkinter for this.
The entire solution consists of two parts:
hide/restore tkinter window
create/delete systray object
Tkinter has no functionality to work with the system tray.
(root.iconify() minimizes to the taskbar, not to the tray)
step 1) (more info) can be done by
window = tk.Tk()
window.withdraw() # hide
window.deiconify() # show
step 2) can be done by site-packages, e.g. pystray
(an example, the same example, and more info)
You can use the wm_protocol specifically WM_DELETE_WINDOW protocol. It allows you to register a callback which will be called when the window is destroyed. This is an simple example:
import tkinter as tk
root = tk.Tk()
root.protocol("WM_DELETE_WINDOW", root.iconify)
root.mainloop()
.iconify turns the window into an icon in System Tray.
import tkinter as tk
root = tk.Tk()
root.mainloop()
import tkinter as tk
root = tk.Tk()
app = tk.Frame(root)
app.mainloop()
After running each of these, the results seem the same.
Any advantage to using tk.Frame()?
Tk creates the root window. Every tkinter application must have a root window. When you instantiate it you also create a tcl interpreter that is used by tkinter.
Frame is just a widget, designed to be a container for other widgets. It cannot act as a standalone window. An instance of Frame cannot exist without an instance of Tk -- if you don't explicitly create an instance of Tk, one will be created for you.
In your example there is no advantage to using frame because you a) don't make it visible with pack, place, or grid, and b) you don't put anything in it.
There are many advantages to using frames, but the main one is that it makes it easy to organize your widgets into logical groups.
I am having a problem between the python shell in my IDE and the Tkinter window. What I am trying to do is have all of my user input in the shell, and then I would like to output the corresponding information in a Tkinter window.
However, when my window is made and pops up, I close it to continue my program in the shell, then I continue with input. However, when I try to reinitialize my window. It says that the window has been destroyed. I understand what this means so I tried having a Toplevel window where I output my info which can be closed, and hide my root window, but the shell will not continue until I close/destroy the root window as well.
Is there a way I can continue in the shell without destroying my root window? I am fairly new to this language so any help would be very much appreciated.
This is my general idea:
from Tkinter import *
#get all my info from the shell
root = Tk()
root.withdraw() #hide the root window
main = Toplevel()
#this is the window that I want to be able to close and open later
#get more info from the shell after main is closed
#now I want to open the updated main window
Thanks in advance! (And I am working on Windows if that matters)
I'm not sure if the way you are trying to do this is the most efficient way, but i would propose these changes so far:
from Tkinter import *
#get all my info from the shell
window = Tk()
window.iconify() #hide the root window
#get more info from the shell after main is closed
window.deiconify()
window.mainloop() # to handle events
i renamed your root-Window to make it more clear for you whats happening and removed the superflous (imho) additional Toplevel-window!
Also keep in mind, that you won't accomplish anything without the mainloop and the necessary event-handlers!
Simply put, this is not how Tkinter is designed to work. Tkinter was designed to have a single root window that is created once, and with a single eventloop that is running. Using it any other way is bound to lead to undesired behavior.
If you really need code to work this way, gather your input from your shell in one process, then use a separate process to display the tkinter window. You can either communicate from one the other using a socket, or you could pass the data from the parent to the child via arguments or environment variables or temporary files.