Problems with 2 different GUI windows - python

So my first GUI window is meant for taking input from user :
from tkinter import *
from main import *
root = Tk()
root.configure(background="orange")
root.wm_title("Python Project")
label_1 = Label(root, text="Project Name",bg="orange",fg="black")
label_2 = Label(root, text="Site URL Link",bg="orange",fg="black")
entry_1 = Entry(root)
entry_2 = Entry(root)
label_1.grid(row=0,sticky=W)
label_2.grid(row=3333,sticky=W)
entry_1.grid(row=0,column=1,padx=50,ipadx=100)
entry_2.grid(row=3333,column=1,ipadx=100)
def callback():
a1 = entry_1.get()
a2 = entry_2.get()
mmm(a1,a2,root) # main program
button1 = Button(root,text="Run",command=callback)
button2=Button(root,text="Quit",command=root.quit)
button1.grid(row=3334,ipadx=15,padx=50,column=1)
button2.grid(row=3335,column=1,ipadx=15,padx=50)
root.mainloop()
And then i use another GUI window someone in this forum made to show my results :
from tkinter import *
root = Tk()
textbox = Text(root)
textbox.pack()
def redirector(inputStr):
textbox.insert(INSERT, inputStr)
sys.stdout.write = redirector # whenever sys.stdout.write is called, redirector is called.
sys.stderr.write = redirector
root.mainloop()
Now every time i run the first GUI , both GUIs open although there is no way the code reached the second GUI code yet... What is the problem here?
Also the second GUI is supposed to print from a class , but i have a bunch of error when I try to just put it there . What changes I need to make so I can make this 2nd GUI work with a class?

Related

Why do I get an extra empty window in Tkinter?

Here is my code:
from tkinter import *
OPTIONS = ["Available","Busy","Invisible","Away"]
now = Toplevel()
variable = StringVar(now)
variable.set(OPTIONS[0]) # default value
details = {"U_status":""}
def verify():
global u_status
details["U_status"]=variable.get()
print ("value is:" + variable.get())
now.destroy()
def status():
w = OptionMenu(now, variable, *OPTIONS)
w.pack()
button = Button(now, text="OK", command=verify, relief='flat')
button.pack()
if __name__=='__main__':
status()
mainloop()
While running the above code, along with the window (I wanted) another empty window appears. Can anyone figure out what is wrong in this code?
Here now = Toplevel() should be replaced with Tk(), like:
now = Tk()
When you use Toplevel() a Tk() window is made in the background, if its not already made(your case), and that is the reason you are getting a blank new window. Actually that blank window is your main window.
Toplevel() is used to make child windows for the parent Tk() windows,ie, if you want sub windows within your main window(now), you will use Toplevel(). Because more than one Tk() in your code will cause some errors later on.
The blank window is actually the root window of your app that tkinter creates by default. You probably want to be explicit, and create a tk.Tk() root, and keep a reference to it.
New windows can be spawned and destroyed at leisure; your app will continue to exist as long as you keep the root active.
Maybe something like this:
import tkinter as tk
def verify():
now = tk.Toplevel(root)
details["U_status"] = variable.get()
txt = f'value is: {details["U_status"]}'
tk.Label(now, text=txt).pack()
now.after(3000, now.destroy)
def status():
tk.OptionMenu(root, variable, *OPTIONS).pack()
tk.Button(root, text="OK", command=verify, relief='flat').pack()
if __name__=='__main__':
OPTIONS = ["Available", "Busy", "Invisible", "Away"]
root = tk.Tk()
variable = tk.StringVar(root)
variable.set(OPTIONS[0])
details = {"U_status": ""}
status()
root.mainloop()

Tkinter gives following error in python 3.6: TclError: NULL main Window

I am writing a python program which executes the following sequence:
1. Dialog box to open/select a directory
2. perform certain operations
3. rename the file using a tkinter dialog box
4. Perform rest of the operations
I have written the following code:
def open_directory():
directory_name = filedialog.askdirectory(title='Ordner Auswählen',parent=root)
print(directory_name)
root.destroy()
def input_name():
def callback():
print(e.get())
root.quit()
e = ttk.Entry(root)
NORM_FONT = ("Helvetica", 10)
label = ttk.Label(root,text='Enter the name of the ROI', font=NORM_FONT)
label.pack(side="top", fill="x", pady=10)
e.pack(side = 'top',padx = 10, pady = 10)
e.focus_set()
b = ttk.Button(root, text = "OK", width = 10, command = callback)
b.pack()
def close_window():
root.destory()
root = tk.Tk()
root.withdraw()
open_directory() #dialogue box to select directory
<perform certain operations>
input_name() #dialgue box for user input file name
root.mainloop()
close_window() #exit the mainloop of tkinter
<perform rest of the functions>
but I get the following error
Tclerror: NULL main window
I think it is realted to declaring root as the main window, but I dont seem to find where I have made the mistake.
Is there some other method, which is better, for what I am trying to do here?
As #CommonSense has mentioned, when you use withdraw to hide the main window, then you need to use the method deiconify to use the root again. Hence, change the function change_directory as follows:
def open_directory():
directory_name = filedialog.askdirectory(title='Ordner Auswählen',parent=root)
print(directory_name)
root.deiconify()
If you do not deiconify the window, you could not call the function input_name, which makes use of the root window.
I have tested this code and it works.
PS: You also have a typo in the function close_window (when destroying the window).
Your use of .destroy() and .quit() as #CommonSense truly said do not really seem well planned.
Not only that, you need to use triggers or events to control your function calls, else they just run straight the one preventing the other from running as is the case in your code.
You should also control when close_window() is called with an event:
from tkinter import filedialog
import tkinter as tk
def open_directory():
directory_name = filedialog.askdirectory(title='Ordner Auswählen',parent=root)
print(directory_name)
#root.destroy()
input_name()
def input_name():
def callback():
print(e.get())
#root.quit()
es_variable=tk.StringVar()
e = tk.Entry(root, textvariable=es_variable)
NORM_FONT = ("Helvetica", 10)
label = tk.Label(root,text='Enter the name of the ROI', font=NORM_FONT)
label.pack(side="top", fill="x", pady=10)
e.pack(side = 'top',padx = 10, pady = 10)
e.focus_set()
b = tk.Button(root, text = "OK", width = 10, command = callback)
b.pack()
def close_window():
root.destory()
root = tk.Tk()
#root.withdraw()
open_dir_button = tk.Button(root, text = "Open Dialog", width = 10, command =open_directory)
open_dir_button.pack()
#dialogue box to select directory
#<perform certain operations>
#dialgue box for user input file name
root.mainloop()
#close_window() #exit the mainloop of tkinter
#<perform rest of the functions>

How do I get the Entry's value in tkinter?

I'm trying to use Tkinter's Entry widget. I can't get it to do something very basic: return the entered value. Does anyone have any idea why such a simple script would not return anything? I've tried tons of combinations and looked at different ideas.
This script runs but does not print the entry:
from Tkinter import *
root = Tk()
E1 = Entry(root)
E1.pack()
entry = E1.get()
root.mainloop()
print "Entered text:", entry
Seems so simple.
Edit
In case anyone else comes across this problem and doesn't understand, here is what ended up working for me. I added a button to the entry window. The button's command closes the window and does the get() function:
from Tkinter import *
def close_window():
global entry
entry = E.get()
root.destroy()
root = Tk()
E = tk.Entry(root)
E.pack(anchor = CENTER)
B = Button(root, text = "OK", command = close_window)
B.pack(anchor = S)
root.mainloop()
And that returned the desired value.
Your first problem is that the call to get in entry = E1.get() happens even before your program starts, so clearly entry will point to some empty string.
Your eventual second problem is that the text would anyhow be printed only after the mainloop finishes, i.e. you close the tkinter application.
If you want to print the contents of your Entry widget while your program is running, you need to schedule a callback. For example, you can listen to the pressing of the <Return> key as follows
import Tkinter as tk
def on_change(e):
print e.widget.get()
root = tk.Tk()
e = tk.Entry(root)
e.pack()
# Calling on_change when you press the return key
e.bind("<Return>", on_change)
root.mainloop()
from tkinter import *
import tkinter as tk
root =tk.Tk()
mystring =tk.StringVar(root)
def getvalue():
print(mystring.get())
e1 = Entry(root,textvariable = mystring,width=100,fg="blue",bd=3,selectbackground='violet').pack()
button1 = tk.Button(root,
text='Submit',
fg='White',
bg= 'dark green',height = 1, width = 10,command=getvalue).pack()
root.mainloop()

Multiple windows open at once in python

I've searched and found a few things on parent windows in python but that is not what I was looking for. I am trying make a simple program that opens a window and another window after that when the previous one is closed. I was also trying to implement some kind of loop or sleep time to destroy the window by default if the user does not. This is what I have (I'm new please don't laugh)
from tkinter import *
import time
root = Tk()
i = 0
if i < 1:
root.title("title")
logo = PhotoImage(file="burger.gif")
w1 = Label(root, image=logo).pack()
time.sleep(3)
root.destroy()
i = i + 1
if i == 1:
root.title("title")
photoTwo = PhotoImage(file="freedom.gif")
labelTwo = Label(root, image=photoTwo).pack()
time.sleep(3)
root.destroy()
i = i + 1
mainloop.()
Perhaps you're looking for something like this:
from tkinter import *
import time
def openNewWindow():
firstWindow.destroy()
secondWindow = Tk()
secondWindow.title("Second Window")
photoTwo = PhotoImage(file="freedom.gif")
labelTwo = Label(secondWindow, image=photoTwo).pack()
secondWindow.mainloop()
firstWindow = Tk()
firstWindow.title("First Window")
logo = PhotoImage(file="burger.gif")
w1 = Label(firstWindow, image=logo).pack()
closeBttn = Button(firstWindow, text="Close!", command=openNewWindow)
closeBttn.pack()
firstWindow.mainloop()
This creates a button in the first window, which the user clicks. This then calls the openNewWindow function, which destroys that window, and opens the second window. I'm not sure there's a way to do this using the window exit button.
To get create a more sustainable window creation, use this:
from tkinter import *
import time
def openThirdWindow(previouswindow):
previouswindow.destroy()
thirdWindow = Tk()
thirdWindow.title("Third Window")
photoTwo = PhotoImage(file="freedom.gif")
labelTwo = Label(thirdWindow, image=photoTwo).pack()
thirdWindow.mainloop()
def openSecondWindow(previouswindow):
previouswindow.destroy()
secondWindow = Tk()
secondWindow.title("Second Window")
photoTwo = PhotoImage(file="freedom.gif")
labelTwo = Label(secondWindow, image=photoTwo).pack()
closeBttn = Button(secondWindow, text="Close!", command= lambda: openThirdWindow(secondWindow))
closeBttn.pack()
secondWindow.mainloop()
def openFirstWindow():
firstWindow = Tk()
firstWindow.title("First Window")
logo = PhotoImage(file="burger.gif")
w1 = Label(firstWindow, image=logo).pack()
closeBttn = Button(firstWindow, text="Close!", command= lambda: openSecondWindow(firstWindow))
closeBttn.pack()
firstWindow.mainloop()
openFirstWindow()
This places the opening of each window in a seperate function, and passes the name of the window through the button presses into the next function. Another method would be setting the window names as global, but this is messy.
The function "lambda:" calls the function, in tkinter you must type this if you want to pass something through a command.
We initiate the whole process first first called "openFirstWindow()"

How to make a button open a new window?

I am making a simple GUI that starts with a main menu them the user can click a button to proceed to a new window which has a picture of a keyboard and the user can press key on their keyboard to play the paino. Right now I cant figure out how to make a button that when pressed closes the main menu (labeled mainMenu()) and open the game menu (playGame).
import tkinter
from tkinter import *
class mainMenu:
def _init_(self, master):
frame = Frame(master)
frame.pack()
self.quitButton = Button(frame, text = "Quit", command = frame.quit)
self.quitButton.pack(side = LEFT)
self.proceedButton = Button(frame, text = "Play", command = playGame)
self.proceedButton.pack(side = LEFT)
def playGame(self):
frame.quit
gameMenu()
def gameMenu(self):
root = Tk()
b = mainMenu(root)
topFrame = Frame(root)
topFrame.pack()
bottomFrame = Frame(root)
bottomeFrame.pack(side = BOTTOM)
photo = PhotoImage(file = "piano.png")
label = Label(root, image = photo)
label.pack()
root.mainloop()
You'll have to forgive me for removing your class but I've never personally worked with classes in python before. However I seem to have you code working to some degree.
import tkinter
from tkinter import *
def playGame():
frame.quit
gameMenu()
def gameMenu():
b = mainMenu(root)
topFrame = Frame(root)
topFrame.pack()
bottomFrame = Frame(root)
bottomFrame.pack(side = BOTTOM)
photo = PhotoImage(file = "piano.png")
label = Label(root, image = photo)
label.pack()
root=Tk()
frame = Frame(root)
frame.pack()
quitButton = Button(frame, text = "Quit", command = frame.quit)
quitButton.pack(side = LEFT)
proceedButton = Button(frame, text = "Play", command = playGame)
proceedButton.pack(side = LEFT)
root.mainloop()
The main problem you had was that you were using both root and master. When declaring the main window in tkinter you normally use either root = Tk() or master = Tk() either one is acceptable, personally I use master. This variable contains the main window that everything else is placed into. You also hadn't put Tk() into any variable, meaning that when you hit root.mainloop() there was nothing to enter the main loop, this was because you were trying to declare root = Tk() inside gameMenu, which wasn't getting called in your program.
If you want to open windows within tkinter it's probably easier to write something like this:
from tkinter import *
master = Tk() #Declaring of main window
def ProceedButtonCommand(mainframe, master): #Command to attach to proceed button
mainframe.destroy()
DrawSecondScreen(master) #This line is what lets the command tied to the button call up the second screen
def QuitButtonCommand(master):
master.destroy()
def DrawFirstScreen(master):
mainframe = Frame(master) #This is a way to semi-cheat when drawing new screens, destroying a frame below master frame clears everything from the screen without having to redraw the window, giving the illusion of one seamless transition
ProceedButton = Button(mainframe, text="Proceed", command=lambda: ProceedButtonCommand(mainframe, master)) #Lambda just allows you to pass variables with the command
QuitButton = Button(mainframe, text = "Quit", command=lambda: QuitButtonCommand(master))
mainframe.pack()
ProceedButton.pack()
QuitButton.pack()
def DrawSecondScreen(master):
mainframe = Frame(master)
Label1 = Label(mainframe, text="Temp")
mainframe.pack()
Label1.pack()
DrawFirstScreen(master)
master.mainloop() #The mainloop handles all the events that occur in a tkinter window, from button pressing to the commands that a button runs, very important
This little script just draws a screen with two buttons, one draws a new screen with the text "temp" on it and the other button closes the master window.
In the future it's probably a better idea to ask a friend who is experienced in programming to help with this kind of stuff. Get talking on some computing forums, I'm sure you'll find a group of sharing and fixing code quickly.

Categories