Second popup box appears when opening a textbox - python

I've got some code that opens a textbox so the user can input an EAN and then it scrapes the web. It all works fine except for some reason a mysterious second textbox opens with the original one and unless you use that one to close the program, it stops responding.
class MyDialog:
def __init__(self, parent): #Pop-up textbox
top = self.top = Toplevel(parent)
Label(top, text="Product EAN").pack() #pop-up box text
self.e = Entry(top, cursor = "xterm", width=25) #Input textbox
self.e.pack(padx=40)
b = Button(top, text="Submit", command=self.ok, cursor = "hand2") #Submit button for pop-up box
b.pack(pady=5)
....
root = Tk()
d = MyDialog(root)
root.wait_window(d.top)
That's all the code to do with textboxes - self.ok is the scraper so is unimportant to this issue. Could someone explain to me or help me fix the issue as I can't see why the following picture is the output from that.
Thank you in advance.

The problem is you are opening a Tk() window and then another, TopLevel() window on top of that, if all you want is one window, the you just use the Tk() window. (The problem is a little unclear, but this is what I assume you are asking).
To fix this you can just remove the TopLevel() window. Like so:
class MyDialog:
def __init__(self, parent): #Pop-up textbox
Label(parent, text="Product EAN").pack() #pop-up box text
self.e = Entry(parent, cursor = "xterm", width=25) #Input textbox
self.e.pack(padx=40)
b = Button(parent, text="Submit", command=self.ok, cursor = "hand2") #Submit button for pop-up box
b.pack(pady=5)
root = Tk()
d = MyDialog(root)
root.mainloop()

Related

Python 2.7: Widget Doesn't Destroy When Radiobutton is Clicked More Than Once

My code shows FunctionAllocation label and two radio buttons, and once one radio button is clicked, it shows Subject ID label and its entry bar. Once return key is clicked, all widgets are destroyed and new message appears.
Everything works smoothly if radio button is clicked once. However, if I click a radio button and then click another radio button, Subject ID label and its entry bar do not disappear despite .destroy() command.
How do I make sure the widgets disappear no matter which & how many times the radio buttons are pressed?
Thank you so much in advance!
from Tkinter import *
class Application(Frame):
#Initial Settings
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.radioButtons()
#Place Initial Buttons
def radioButtons(self):
#Variable to tie two radio buttons
self.tieVar1 = StringVar()
#Text before FA buttons
self.buttonLabel1 = Label(root, text="Function Allocation:")
self.buttonLabel1.place(relx=0.35, rely=0.3, anchor=CENTER)
#Two Radio FA buttons
self.radio1 = Radiobutton(text = "FA_F", variable=self.tieVar1, value="FA1", command=lambda: self.addSubject())
self.radio1.place(relx=0.5, rely=0.3, anchor=CENTER)
self.radio2 = Radiobutton(text = "FA_I", variable=self.tieVar1, value="FA2", command=lambda: self.addSubject())
self.radio2.place(relx=0.6, rely=0.3, anchor=CENTER)
def addSubject(self):
#Text before ID entry bar
self.buttonLabel2 = Label(root, text="Subject ID:")
self.buttonLabel2.place(relx=0.35, rely=0.6, anchor=CENTER)
#ID entry bar
self.myEntry = Entry()
self.myEntry.place(relx=0.5, rely=0.6, anchor=CENTER)
self.contents = StringVar()
self.contents.set("Sample Text")
self.myEntry["textvariable"] = self.contents
self.myEntry.bind('<Key-Return>', self.reset_contents)
#Action when return key pressed after typing subject ID
def reset_contents(self, event):
#Delete all
self.buttonLabel1.destroy()
self.buttonLabel2.destroy()
self.radio1.destroy()
self.radio2.destroy()
self.myEntry.destroy()
#Setting up new window
self.setActions()
def setActions(self):
Label(text="Done!", font=("Times", 10, "bold")).place(relx=0.5, rely=0.5, anchor=CENTER)
#Final settings to keep window open
root = Tk()
root.geometry("1000x400")
app = Application(master=root)
app.mainloop()
You are making a new Label and Entry every time you click that button. However your destroy only destroys the last one created. The easiest fix is to simply check if the Label has already been created:
def addSubject(self):
if hasattr(self, 'buttonLabel2'):
return # abort this method if the Label is already created
# rest of your method
Unrelated, but if you want your Radiobuttons to start in a blank state rather than a tristate, you need to initialize the StringVar like this:
self.tieVar1 = StringVar(value='Novel')

python child Tk window

I have a code where I have a drop down menu and what I need to do is that when I select an entry from the drop down list (ex: Send an email) and press on go, I need this to populate another tk window (child window).
I know I am doing something wrong but can not comprehend how to overcome this, I have been searching for a while but I am unable to find a solution or guidance on how to complete this.
Thanks in advance for your help with this!
from tkinter import *
root = Tk()
root.geometry("400x100")
#========================================
#Entry area to enter the number
labelmain = Label(root,text="Please enter number:")
labelmain.pack()
entryvar = StringVar(root)
entrymain = Entry(root, textvariable=entryvar,width=30)
entrymain.pack()
#========================================
#Create option drop down list:
lst = ["Save details to DB", "Send an email", "Copy format", "email", "View report"]
ddl = StringVar(root)
ddl.set(lst[0])
option = OptionMenu(root, ddl, *lst)
option.pack()
#========================================
#Function to get the values from drop down list
def ok():
print("value is: " + ddl.get())
#root.quit()
#=========================================
#Button to process the selection:
btnmain = Button(root,text="Go", command=ok)
btnmain.pack()
#=========================================
if ddl.get() == "Send an email":
samepmrdb = Tk()
samepmrdb.mainloop()
root.mainloop()
You are checking the value of ddl right after you open up your window. As you said in your question, you want some stuff happen after pressing the button so you need to put those codes under the command of said button.
Also, a tkinter app should only have one Tk() instance and one mainloop. When you want to open another window, you should use Toplevel().
def ok():
print("value is: " + ddl.get())
if ddl.get() == "Send an email":
samepmrdb = Toplevel()
#now you can populate samepmrdb as you like
If all you're looking to do is find a way to update a second tkinter window with the selection from an OptionMenu on the first tkinter window this can be achieved easily using the below code:
from tkinter import *
class App:
def __init__(self, master):
self.master = master
self.top = Toplevel(master)
self.master.withdraw()
self.var = StringVar()
self.var.set("Example1")
self.option = OptionMenu(self.top, self.var, "Example1", "Example2", "Example3", "Example4")
self.button = Button(self.top, text="Ok", command=lambda:self.command(self.var))
self.label = Label(self.master)
self.option.pack()
self.button.pack()
self.label.pack()
def command(self, var):
self.master.deiconify()
self.label.configure(text=var.get())
self.label.pack()
root = Tk()
app = App(root)
root.mainloop()
This creates a Toplevel widget which contains an OptionMenu and Button widget. The Button widget will then output the selection from the OptionMenu widget when pressed.
This kind of logic can be used for all sorts of things and it's relatively simple to pass information from one window to another, provided this is what your question is asking.

Tkinter Toplevel widget get user input multiple times

I am trying to get user input using a Toplevel widget in order to create an order but the submit button does not work as expected please assist.
def spawn_window(self):
top = Toplevel()
top.title("Available Electronics")
self.entrytext = StringVar()
Entry(top, textvariable=self.entrytext).pack()
button = Button(top, text="Dismiss", command=top.destroy)
button.pack(side='right')
submit = Button(top, text ="Submit", command = self.datainput)
submit.pack(side='left')
def datainput(self):
input_var = self.entrytext.get()
self.devices.append(input_var)
"wanted the text box to turn blank as soon as the submit button was clicked in order to create room for another entry" now its clear what you really want!
In your datainput-method just clear your stringvar at the end, like this:
def datainput(self):
input_var = self.entrytext.get()
self.devices.append(input_var)
self.entrytext.set("")

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.

Tkinter Button does not appear on TopLevel?

This is a piece of code I write for this question: Entry text on a different window?
It is really strange what happened at mySubmitButton, it appears that the button does not want to appear when it is first started, it will, however appear when you click on it. Even if you click on it and release it away from the button, that way it won't be send. I am suspecting if this only happen on a mac, or it only happen to my computer, because it is a very minor problem. Or it is something silly I did with my code.
self.mySubmitButton = tk.Button(top, text='Hello', command=self.send)
self.mySubmitButton.pack()
Am I missing something? I googled and found this question and answer on daniweb. And I do a diff on them, can't figure out what he did "fixed", but I did see the line is changed to command=root.quit. But it is different from mine anyway...
Here is the full source code, and there is no error message, but the button is just missing.
import tkinter as tk
class MyDialog:
def __init__(self, parent):
top = self.top = tk.Toplevel(parent)
self.myLabel = tk.Label(top, text='Enter your username below')
self.myLabel.pack()
self.myEntryBox = tk.Entry(top)
self.myEntryBox.pack()
self.mySubmitButton = tk.Button(top, text='Hello', command=self.send)
self.mySubmitButton.pack()
def send(self):
global username
username = self.myEntryBox.get()
self.top.destroy()
def onClick():
inputDialog = MyDialog(root)
root.wait_window(inputDialog.top)
print('Username: ', username)
username = 'Empty'
root = tk.Tk()
mainLabel = tk.Label(root, text='Example for pop up input box')
mainLabel.pack()
mainButton = tk.Button(root, text='Click me', command=onClick)
mainButton.pack()
root.mainloop()
Adding another button right after this one, the second one actually appear. I thought it might be because I didn't call the same function, but I called the same one and it does the exact same thing it appears...
Adding a empty label between them, doesn't work. The button still isn't being draw.
PS: I am using Mac OS 10.5.8, and Tk 8.4.7.
I see the hello button, but I'm on windows 7.
I did a quick re-write of your example. I'll be curious if it makes any difference for you.
import tkinter as tk
class GUI(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
mainLabel = tk.Label(self, text='Example for pop up input box')
mainLabel.pack()
mainButton = tk.Button(self, text='Click me', command=self.on_click)
mainButton.pack()
top = self.top = tk.Toplevel(self)
myLabel = tk.Label(top, text='Enter your username below')
myLabel.pack()
self.myEntryBox = tk.Entry(top)
self.myEntryBox.pack()
mySubmitButton = tk.Button(top, text='Hello', command=self.send)
mySubmitButton.pack()
top.withdraw()
def send(self):
self.username = self.myEntryBox.get()
self.myEntryBox.delete(0, 'end')
self.top.withdraw()
print(self.username)
def on_click(self):
self.top.deiconify()
gui = GUI()
gui.mainloop()

Categories