When I run this script, two windows appear, one for the file selection and the Tkinter window. How can I change this so that the Tkinter window only opens after a file has been selected? Thanks
def main():
my_file = askopenfilename()
stage1()
def stage1():
master = Tk()
master.mainloop()
The window master does open only after the file dialog closure (try to change its title to check), the first window you see is the parent window of the file dialog. Indeed, the tkinter file dialogs are toplevel windows, so they cannot exist without a parent window. So the first window you see is the parent window of the file dialog.
The parent window can however be hidden using the withdraw method and then restored with deiconify:
from tkinter import Tk
from tkinter.filedialog import askopenfilename
def main():
master = Tk()
master.withdraw() # hide window
my_file = askopenfilename(parent=master)
master.deiconify() # show window
master.mainloop()
if __name__ == '__main__':
main()
Related
I would like to disable the main window of my text adventure program while the character creation window is up. I am relatively new to this. When I try my code below, the main window stays interactable even though the secondary window (creator) is open. There is no error that the console puts out, it just doesn't work is all.
def characterCreator():
global creator
creator = Tk()
creator.title('Character Creator')
creator.geometry('300x400')
while creator.state=='normal':
root.state='disabled'
You should create your creator window as an instance of tkinter.Toplevel() rather than declaring a new instance of Tk() altogether, then you can use grab_set to prevent the user from interacting with the root window while the creator window is open.
import tkinter as tk
root = tk.Tk()
# usual root configs like title and geometry go here
creator = tk.Toplevel(root) # the Toplevel window is a child of the root window
# creator geometry and title and so on go here
creator.grab_set() # keep window on top
if __name__ == '__main__':
root.mainloop()
I am opening other windows from a single tkinter button as shown here:
https://www.pythontutorial.net/tkinter/tkinter-toplevel/
The code shown there is
import tkinter as tk
from tkinter import ttk
class Window(tk.Toplevel):
def __init__(self, parent):
super().__init__(parent)
self.geometry('300x100')
self.title('Toplevel Window')
ttk.Button(self,
text='Close',
command=self.destroy).pack(expand=True)
class App(tk.Tk):
def __init__(self):
super().__init__()
self.geometry('300x200')
self.title('Main Window')
# place a button on the root window
ttk.Button(self,
text='Open a window',
command=self.open_window).pack(expand=True)
def open_window(self):
window = Window(self)
window.grab_set()
if __name__ == "__main__":
app = App()
app.mainloop()
If I run this program, it is not possible to hit the "Open a window" button twice to get two Toplevel instances. I would like to get as many instances as I like to with only one button. Is this possible somehow?
Consider this line of code:
window.grab_set()
This is setting a grab on the first window that is created. That means that all events from both the keyboard and the mouse are funneled to the first window that is created. That means you can no longer click on the button in the root window until the grab has been removed. Note that if the window is destroyed, the grab is automatically removed.
Grabs are typically used when creating a modal dialog -- a dialog which requires user input before the program can continue. By doing a grab, you insure that the user can't interact with the main program until they've interacted with the dialog.
The solution is simple: remove the call to window.grab_set() if your goal is to be able to open multiple windows which can all be used at the same time.
Simply remove window.grab_set(). The grab_set() method routes all events for this application to this widget. Whatever events generated like button-click or keypress is directed to another window.
def open_window(self):
window = Window(self)
So you know how when you use Notepad (on Windows), for example, and you want to open an old file? You click file, then open, then a file dialog opens ups and you can select the file you want, and the program will display its contents.
Basically, I want to make a button in Python that can do that exact thing.
Here's my function for the button-
def UploadAction():
#What to do when the Upload button is pressed
from tkinter import filedialog
When I click on the button assigned to this action, nothing happens, no errors, no crash, just nothing.
import tkinter as tk
from tkinter import filedialog
def UploadAction(event=None):
filename = filedialog.askopenfilename()
print('Selected:', filename)
root = tk.Tk()
button = tk.Button(root, text='Open', command=UploadAction)
button.pack()
root.mainloop()
I created a couple of GUIs using tkinter. But now I am interested in combining them into one caller GUI. So the caller GUI would have buttons that, when clicked, would open the other GUIs. However, I cannot get it to work. I've done the imports correctly (I think), edited the main functions in the subGUIs, and added the command=GUI.main in my buttons. I get it to load but I get errors about missing files...but when I run a GUI by itself it works fine.
In my research, I read that there can only be one mainloop in a Tkinter program. Basically, I cannot use a Tkinter GUI to call another Tkinter GUI. Do you know what I can do different, for instance, can I create the caller GUI using wxPython and have it call all other GUIs that use Tkinter?
Thank you!
You can't "call" another GUI. If this other GUI creates its own root window and calls mainloop(), your only reasonable option is to spawn a new process. That's a simple solution that requires little work. The two GUIs will be completely independent of each other.
If you have control over the code in both GUIs and you want them to work together, you can make the base class of your GUI a frame rather than a root window, and then you can create as many windows as you want with as many GUIs as you want.
For example, let's start with a simple GUI. Copy the following and put it in a file named GUI1.py:
import tkinter as tk
class GUI(tk.Frame):
def __init__(self, window):
tk.Frame.__init__(self)
label = tk.Label(self, text="Hello from %s" % __file__)
label.pack(padx=20, pady=20)
if __name__ == "__main__":
root = tk.Tk()
gui = GUI(root)
gui.pack(fill="both", expand=True)
tk.mainloop()
You can run that GUI normally with something like python GUI1.py.
Now, make an exact copy of that file and name it GUI2.py. You can also run it in the same manner: python GUI2.py
If you want to make a single program that has both, you can create a third file that looks like this:
import tkinter as tk
import GUI1
import GUI2
# the first gui owns the root window
win1 = tk.Tk()
gui1 = GUI1.GUI(win1)
gui1.pack(fill="both", expand=True)
# the second GUI is in a Toplevel
win2 = tk.Toplevel(win1)
gui2 = GUI2.GUI(win2)
gui2.pack(fill="both", expand=True)
tk.mainloop()
Depending on your OS and window manager, one window might be right on top of the other, so you might need to move it to see both.
Thank you for the ideas. At first, your code wouldn't print the text on the toplevel window. So I edited it a little and it worked! Thank you. GUI1 and GUI2 look like:
import tkinter as tk
def GUI1(Frame):
label = tk.Label(Frame, text="Hello from %s" % __file__)
label.pack(padx=20, pady=20)
return
if __name__ == "__main__":
root = tk.Tk()
GUI1(root)
root.mainloop()
And then the caller looks like this:
from tkinter import *
import GUI1
import GUI2
def call_GUI1():
win1 = Toplevel(root)
GUI1.GUI1(win1)
return
def call_GUI2():
win2 = Toplevel(root)
GUI2.GUI2(win2)
return
# the first gui owns the root window
if __name__ == "__main__":
root = Tk()
root.title('Caller GUI')
root.minsize(720, 600)
button_1 = Button(root, text='Call GUI1', width='20', height='20', command=call_GUI1)
button_1.pack()
button_2 = Button(root, text='Call GUI2', width='20', height='20', command=call_GUI2)
button_2.pack()
root.mainloop()
I'd like to use the tab key in both showing of the following code:
from tkinter import *
main = Tk()
def pressButton():
main.destroy()
End=Button(main,text='Finished',width=15,command=pressButton).grid()
main.mainloop()
from tkinter import *
main = Tk()
def pressButton():
main.destroy()
End=Button(main,text='Finished',width=15,command=pressButton).grid()
main.mainloop()
first window works: i can press tab and space and it opens the second window; there i'm not able to "press button" by using tab and space, because the cursor is in Python Shell.
How can I get the cursor in the second window?
As mention in that post "Tkinter main window focus", it is possible to force the focus to the main window.
Solution - add a call to the after() to focus_force().
from tkinter import *
main = Tk()
def pressButton():
main.destroy()
End=Button(main,text='Finished',width=15,command=pressButton).grid()
# call the focus_force() after the window is displayed
main.after(1, lambda: main.focus_force())
main.mainloop()