Python Tkinter destroy window with a method - python-3.x

I'm a new student to Python, I'm sorry if my code is horrible. I'm trying to run a GIF animation of "loading" while the web scrape takes place. The issue is I cant get the toplevel window to destroy after the scrape completes.
I have looked at many videos and other posts on here none have worked. toplevel.destroy() seems to be the common suggestion but its not working.
my main window
class App:
def __init__(self, parent):
self.parent = parent
self.parent.geometry('1000x500+100+100')
self.parent.resizable(width=False, height=False)
self.parent.title('Class Project')
self.canvas1 = tkinter.Canvas(parent, height=500, width=1000)
filename = ImageTk.PhotoImage(file = "background.png")
background_label = tkinter.Label(self.canvas1, image=filename)
background_label.image = filename
The new window
def new_window(self):
self.newWindow = tkinter.Toplevel()
self.app = LoadingScreen(self.newWindow)
class LoadingScreen:
def __init__(self, parent):
self.parent = parent
self.parent.title('Loading....')
self.parent.geometry('350x270+100+100')
self.parent.resizable(width=False, height=False)
self.canvas = tkinter.Canvas(parent)
self.canvas.pack()
after the scrape I call the close
LoadingScreen.close_window()
def close_window():
toplevel.destory()
toplevel.destory()
NameError: name 'toplevel' is not defined
So far every thing works, just can not get the window to close.

Related

Tkinter Label class not appearing when used within a class

I am creating a basic GUI with multiple, but similar, label structures. However, when I created a class to help minimize the text, and placed it within a label frame, the label frame does not appear. This only happens when I use the class within a class, and if I use the regular label and label frame classes everything works out well. I'm trying to figure out as to why this is the case.
My code:
main.py
from tkinter import *
def main():
main_window = Tk()
app = First(main_window)
main_window.mainloop()
class GPULabel(Label):
def __init__(self, master, varText):
varText = varText
super().__init__()
self["text"] = varText
self["anchor"] = "w"
self["width"] = 25
class First:
def __init__(self, root):
self.root = root
self.root.title('First Window')
self.myFrame = LabelFrame(self.root, text="frame")
self.myFrame.pack()
label1 = GPULabel(self.myFrame, "label")
lable1.pack()
if __name__ == '__main__'
main()
This opens a window but it is completely empty. However, if I swap to a regular Label(self.myFrame...) then the window pops up correctly. Why is that? And is there a way to make my original method work?

Tkinter gives me a second window

I am writing code for a tkinter gui using a class, however I notice that when I run there is a second window besides the main one I made. I've tried a number of things but they either break the code or the window is black. See code below.
import tkinter as gui
class loginWindow(gui.Frame):
def __init__(self):
super(loginWindow, self).__init__()
self.logUI()
def logUI(self):
self.mainWindow = gui.Tk()
self.mainWindow.title("GLSC IT Inventory")
self.mainWindow.minsize(400, 150)
self.mainWindow.maxsize(400, 150)
self.mainWindow.geometry("400x150")
self.greet_label = gui.Label(self.mainWindow, text="Welcome!!!")
self.greet_label.place(x=180, y=5)
self.uname_label = gui.Label(self.mainWindow, text="Username:")
self.uname_label.place(x=10, y=24)
self.uname_input = gui.StringVar()
self.uname_field = gui.Entry(self.mainWindow, bd=4, textvariable=self.uname_input)
self.uname_field.place(x=80, y=25, width=160)
self.pwd_label = gui.Label(self.mainWindow, text="Password:")
self.pwd_label.place(x=10, y=54)
self.pwd_input = gui.StringVar()
self.pwd_field = gui.Entry(self.mainWindow, bd=4, textvariable=self.pwd_input, show="\u2022")
self.pwd_field.place(x=80, y=55, width=160)
self.login_button = gui.Button(self.mainWindow, text="Login", command=None)
self.login_button.place(x=180, y=95)
my_app = loginWindow()
my_app.mainloop()
When you create instance of loginWindow(), an instance of Tk() is required but there is none, so it will be created implicitly for you.
Then another instance of Tk() is created inside logUI(). So there are two instances of Tk().
One way to fix it is loginWindow not inherited from Frame:
class loginWindow:
def __init__(self):
self.logUI()
def logUI(self):
...
# add for calling tkinter.mainloop()
def mainloop(self):
self.mainWindow.mainloop()

why does my tk tabbed for loop have an error of "tabs[upper_tabs] = self.tab TypeError: unhashable type: 'list'"

I can create the 2 tabs individually, and I am trying to make it expendable by using a for loop. I get an error that says
tabs[upper_tabs] = self.tab
TypeError: unhashable type: 'list'
I am assuming it's how I reference the dictionary. Would you please help me understand and correct the error.
import tkinter as tk
from tkinter import ttk
upper_tabs = ["Final", "Requests"]
tabs = {}
class Application(ttk.Frame): #inherent from frame.
def __init__(self, parent):
tk.Frame.__init__(self, parent, bg="ivory2")
self.parent = parent
self.pack()
self.tabControl = ttk.Notebook(self, width="900", height= "350") #
Create Tab Control
for names in upper_tabs:
self.tab=ttk.Frame(self.tabControl)# Create a tab
self.tabControl.add(self.tab, text=names) # Add the tab
tabs[names] = self.tab
self.tabControl.pack(expand=1, fill="both") # Pack to make visible
self.grid()
def main():
root = tk.Tk()
root.title("class basic window")
root.geometry("1200x600")
root.config(background="LightBlue4")
app = Application(root)
root.mainloop()
if __name__ == '__main__':
main()
I don't quite understand what you want to do, but to remove the error and make the program look like this...
(Scaled down)
... is to change the line tabs[upper_tabs] = self.tab to tabs[tuple(upper_tabs)] = self.tab.
This works because a tuple cannot change, and it is, therefore, possible to use it as a dictionary key, which a list can't be. For more on python dictionaries, see this page.

Python3 class function definition confusion about NameError

I'm new to programming and this is my first post on the site. I'm sure I'm making a dumb mistake, but I'd really appreciate a push in the right direction. I'm trying to make a calculator, and want to make a function that produces a Button object for numbers. When I try to run this I get the error:
'NameError: name 'num_but_gen' is not defined'
Here is the code:
from tkinter import *
WINDOW_HEIGHT = 300
WINDOW_WIDTH = 325
class Window(Frame):
def __init__(self, master = None):
Frame.__init__(self, master)
self.master = master
self.init_window()
def num_but_gen(self, disp, xloc=0, yloc=0, wid=0, hei=0):
self.Button(text='{}'.format(disp),height=hei, width=wid)
self.place(x=xloc, y=yloc)
def init_window(self):
self.master.title('Calculator')
self.pack(fill=BOTH, expand=1)
Button1 = num_but_gen('1', xloc=0, yloc=200, wid=40, hei=40)
root = Tk()
app = Window(root)
root.geometry("{}x{}".format(WINDOW_WIDTH,WINDOW_HEIGHT))
root.mainloop()
Any help would be greatly appreciated! Also bonus points to anyone with suggestions on how to better phrase my question titles in future posts.
jasonharper is right, you need to add self in front of num_but_gen, but there are other problems in your code.
In num_but_gen:
your window class does not have a Button attribute, so you need to remove self. in front of Button
it is not the Window instance but the button that you want to place
you don't need to use text='{}'.format(disp), text=disp does the same.
In init_window:
you store the result of num_but_gen in a variable, but this function returns nothing so that's useless (and capitalized names should not be used for variables, but for class names only)
the width option of a button displaying text is in letters, not in pixels and its height option is in text lines, so wid=40, hei=40 will create a very big button. If you want to set the button size in pixels, you can do it through the place method instead.
Here is the corresponding code:
import tkinter as tk
WINDOW_HEIGHT = 300
WINDOW_WIDTH = 325
class Window(tk.Frame):
def __init__(self, master = None):
tk.Frame.__init__(self, master)
self.master = master
self.init_window()
def num_but_gen(self, disp, xloc=0, yloc=0, wid=0, hei=0):
button = tk.Button(self, text=disp)
button.place(x=xloc, y=yloc, height=hei, width=wid)
def init_window(self):
self.master.title('Calculator')
self.pack(fill=tk.BOTH, expand=1)
self.num_but_gen('1', xloc=0, yloc=200, wid=40, hei=40)
root = tk.Tk()
app = Window(root)
root.geometry("{}x{}".format(WINDOW_WIDTH,WINDOW_HEIGHT))
root.mainloop()

Unwanted window appears

I've written a short class to create a new window, with a tab menu, and a canvas on one of them. Every time I launch the app two windows show up. One of them is the wanted one, the other one is an empty one. I'm new to OOP in python, I guess I miss something in my class.
class Window(QtGui.QDialog):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.tab1 = QtGui.QWidget()
self.tab2 = QtGui.QWidget()
self.figure = plt.figure()
self.canvas = FigureCanvas(self.figure)
self.layout = QtGui.QVBoxLayout()
self.layout.addWidget(self.canvas)
self.tab1.setLayout(self.layout)
self.tabs = QtGui.QTabWidget()
self.tabs.addTab(self.tab1, "Database")
self.tabs.addTab(self.tab2, "Current")
self.tabs.show()
My mistake was here:
if __name__=='__main__':
app=QtGui.QApplication(sys.argv)
main = GUI.Window()
#main.show()
app.exec_()
The main.show() cause the problem.

Resources