Tkinter - Hide and show main screen from toplevel - python

I am trying to create a main screen that is displayed only if the login is successful, but i cant figure out how to make the main screen visible/invisible
from tkinter import *
class Login_screen(Frame):
def __init__(self,master):
self.open_login()
def open_login(self):
self.root2 = Toplevel()
self.root2.geometry("400x200")
self.grid_forget()
self.app2 = Main_screen(self.root2)
class Main_screen(Frame):
def __init__(self,master):
Frame.__init__(self,master)
self.master.grid()
self.button = Button(master = self,text = "Close",command = lambda: self.close_windows())
self.button.grid()
def close_windows(self):
self.master.destroy()
Login_screen.master.grid()
root = Tk()
root.geometry("800x600")
app = Login_screen(root)
root.mainloop()

I figured out how it works:
from tkinter import *
class Main_screen(Frame):
def __init__(self,master):
Frame.__init__(self, master)
self.grid()
self.text = Label(text="Janela")
self.text.grid()
root.withdraw()
self.create_login()
def create_login(self):
self.root2 = Toplevel()
self.app2 = Login_screen(self.root2)
class Login_screen(Frame):
def __init__(self,master):
Frame.__init__(self,master)
self.grid()
self.botao1 = Button(self,text="Appear",command = lambda: self.show_main())
self.botao1.grid()
def show_main(self):
self.master.destroy()
root.deiconify()
root = Tk()
app = Main_screen(root)
root.mainloop()

Related

Cannot use .place command for tkinter

I use .place command to indicate the place of "TEXT" (100, 70), but cannot reflect in the window even if changing it to any coordinate.
Could you specify the problem?
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.pack()
self.create_widgets()
self.master.geometry("600x300")
def create_widgets(self):
self.msg1 = tk.Label(self, text = "TEXT")
self.msg1.place(x = 100, y = 70)
self.msg1.pack()
if __name__ == "__main__":
root = tk.Tk()
app = Application(master = root)
app.mainloop()
Few corrections to make:
Don't use .pack() geometry manager after .place geometry manager, or pack() will over ride .place() manager:
def create_widgets(self):
self.msg1 = tk.Label(self, text = "TEXT")
self.msg1.place(x = 100, y = 230)
Use fill and expand parameter to pack the Frame:
self.pack(fill=tk.BOTH,expand=1)
Here is the code:
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.pack(fill=tk.BOTH,expand=1)
self.create_widgets()
self.master.geometry("600x300")
def create_widgets(self):
self.msg1 = tk.Label(self, text = "TEXT")
self.msg1.place(x = 100, y = 230)
if __name__ == "__main__":
root = tk.Tk()
app = Application(master = root)
app.mainloop()
Don't use both .pack() and .place(), use one of them instead.
Let's say to use .place():
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.create_widgets()
self.place(relwidth = 1, relheight = 1)
self.master.geometry("600x300")
def create_widgets(self):
self.msg1 = tk.Label(self, text = "TEXT")
self.msg1.place(x = 100, y = 70)
if __name__ == "__main__":
root = tk.Tk()
app = Application(master = root)
app.mainloop()
I replaced self.pack() with self.place(relwidth = 1, relheight = 1), so the frame will be always wide as the window.
Then I deleted self.msg1.pack().
Now it should work.

How to handle a main window button using closing event (Tkinter "X" button)?

Can anyone help me with this. Once I click the button, there will be a new window that pop up and the button will be disabled. How can I enable again the button from win1 after clicking the "X" button on win2?
This is my code:
from tkinter import *
class win1:
def __init__(self, master):
self.master = master
self.master.geometry('200x100+0+0')
self.btn1 = Button(self.master, text='Click', command=self.openwin)
self.btn1.pack()
def openwin(self):
self.openwin2 = Toplevel(self.master)
app = win2(self.openwin2)
self.btn1['state'] = 'disabled'
class win2:
def __init__(self, master):
self.master = master
self.master.geometry('200x100+100+100')
self.btn1 = Label(self.master, text='Click the close button')
self.btn1.pack()
self.master.protocol("WM_DELETE_WINDOW", self.closewin)
def closewin(self):
self.master.btn1['state'] = 'normal'
def main():
root = Tk()
app = win1(root)
root.mainloop()
if __name__ == '__main__':
main()
Traceback:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python\Python385\lib\tkinter\__init__.py", line 1883, in __call__
return self.func(*args)
File "d:/PC Access/Documents/CPET8-8L/GUI/testing.py", line 27, in closewin
self.master.btn1['state'] = 'normal'
AttributeError: 'Toplevel' object has no attribute 'btn1'
here is how I would edit the code:
from tkinter import *
class win1:
def __init__(self, master):
self.master = master
self.master.geometry('200x100+0+0')
self.btn1 = Button(self.master, text='Click', command=self.openwin)
self.btn1.pack()
def openwin(self):
self.openwin2 = Toplevel(self.master)
app = win2(self.openwin2, self)
self.btn1['state'] = 'disabled'
class win2:
def __init__(self, master, main_window):
self.master = master
self.main_window = main_window
self.master.geometry('200x100+100+100')
self.btn1 = Label(self.master, text='Click the close button')
self.btn1.pack()
self.master.protocol("WM_DELETE_WINDOW", self.closewin)
def closewin(self):
self.main_window.btn1['state'] = 'normal'
self.master.destroy()
def main():
root = Tk()
app = win1(root)
root.mainloop()
if __name__ == '__main__':
main()
the parts I changed:
def closewin(self):
self.main_window.btn1['state'] = 'normal'
self.master.destroy()
and this:
class win2:
def __init__(self, master, main_window):
self.master = master
self.main_window = main_window
and this:
def openwin(self):
self.openwin2 = Toplevel(self.master)
app = win2(self.openwin2, self)
self.btn1['state'] = 'disabled'
also I would suggest using those classes differently but You do You (does not seem too bad)

How do I vertically center text in a button?

I have a button within a frame:
self.b = tk.Button(self.subframe1, text="UPDATE", command = self.update)
The text in this button will be centered horizontally but not vertically. Is it possible to do the latter?
As commented by #gandreadis, you can rely on anchor option to do the job.
Here is an MCVE (in Python 3.x):
import tkinter as tk
class Test:
def __init__(self, master):
self.master = master
self.configure_gui()
self.create_widgets()
self.configure_widgets()
def configure_gui(self):
self.master.title("Button Text Centering")
self.master.geometry('300x100')
self.master.resizable(0, 0)
def create_widgets(self):
self.create_demo_button()
def create_demo_button(self):
self.btn_with_centered_text = tk.Button(self.master, text="Centered")
self.btn_with_centered_text.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
self.btn_with_centered_text.config(bg="yellow")
def configure_widgets(self):
self.configure_btn_with_centered_text()
def configure_btn_with_centered_text(self):
self.btn_with_centered_text.config(bg="yellow", relief=tk.RAISED)
self.btn_with_centered_text.config(border="2px")
def main():
root = tk.Tk()
t = Test(root)
root.mainloop()
if __name__ == '__main__':
main()
Demo:

Tkinter - Button created on wrong screen

I am trying to create multiple windows using tkinter , but i am having no success so far ... When i create a child window and put a button on it , the button is created in the parent window!
from tkinter import *
class Login_screen(Frame):
def __init__(self,master):
Frame.__init__(self, master)
self.grid()
self.button1 = Button(text = "Open",command = lambda: self.open_login())
self.button1.grid()
def open_login(self):
self.root2 = Toplevel()
self.root2.geometry("400x200")
self.app2 = Main_screen(self.root2)
class Main_screen(Frame):
def __init__(self,master):
Frame.__init__(self,master)
self.grid()
self.button = Button(text = "Close",command = lambda: self.close_windows())
self.button.grid()
def close_windows(self):
self.grid_forget()
root = Tk()
root.geometry("800x600")
app = Login_screen(root)
root.mainloop()
You need to supply the Button() with the master argument:
self.button = Button(master = self, text = "Close",command = lambda: self.close_windows())
master is the first arg to a widget so it can also be done via: Button(self, text=...)
This is good practice and you should get in the habit of always explicitly providing master, otherwise Tk defaults this arg to None and will place it on the root window.

Is it possible to keep the same window for every class in python's tkinter?

I am trying to create a program in tkinter which allows me to open an initial window then to keep it throughout all classes used. For example, if I was to create a button in a window then when I click this button, it would exuecute a method that destroys the widget, and then executes a new class that builds a new screen within the same window, such as text opposed to a button.
from tkinter import *
class Window1:
def __init__(self, master):
self.master = master
self.label = Button(self.master, text = "Example", command = self.load_new)
self.label.pack()
def load_new(self):
self.label.destroy()
## Code to execute next class
class Window2:
def __init__(self, master):
self.master = master
self.label = Label(self.master, text = "Example")
self.label.pack()
def main():
root = Tk()
run = Window1(root)
root.mainloop()
if __name__ == '__main__':
main()
I understand this is less practical, but I am curious. Cheers.
Tk() creates main window and variable root gives you access to this window. You can use root as argument for Window2 and you will have access to main window inside Window2
from tkinter import *
class Window1:
def __init__(self, master):
# keep `root` in `self.master`
self.master = master
self.label = Button(self.master, text="Example", command=self.load_new)
self.label.pack()
def load_new(self):
self.label.destroy()
# use `root` with another class
self.another = Window2(self.master)
class Window2:
def __init__(self, master):
# keep `root` in `self.master`
self.master = master
self.label = Label(self.master, text="Example")
self.label.pack()
root = Tk()
run = Window1(root)
root.mainloop()
--
Probably nobody use another class to create Label in place of Button ;)
--
EDIT: In this example using names Window1 and Windows2 is misleading because there is only one window and two classes which use this window. I would rather use names FirstOwner, SecondOwner
Everything is implemented in one Tk class and in this case there always is only one window.
from tkinter import *
from tkinter import ttk
class MainWindow():
def __init__(self, mainWidget):
self.main_frame = ttk.Frame(mainWidget, width=300, height=150, padding=(0, 0, 0, 0))
self.main_frame.grid(row=0, column=0)
self.some_kind_of_controler = 0
self.main_gui()
def main_gui(self):
root.title('My Window')
self.main_label_1 = ttk.Label(self.main_frame, text='Object_1')
self.main_label_1.grid(row=0, column=0)
self.main_label_2 = ttk.Label(self.main_frame, text='Object_2')
self.main_label_2.grid(row=1, column=0)
self.main_label_3 = ttk.Label(self.main_frame, text='Object_3')
self.main_label_3.grid(row=2, column=0)
self.setings_button = ttk.Button(self.main_frame, text='Setings')
self.setings_button.grid(row=0, column=1)
self.setings_button.bind('<Button-1>', self.setings_gui)
self.gui_elements = [self.main_label_1,
self.main_label_2,
self.main_label_3,
self.setings_button]
def setings_gui(self, event):
self.gui_elements_remove(self.gui_elements)
root.title('Setings')
self.main_label_1 = ttk.Label(self.main_frame, text='Object_1')
self.main_label_1.grid(row=2, column=0)
self.main_menu_button = ttk.Button(self.main_frame, text='Main menu')
self.main_menu_button.grid(row=0, column=1)
self.main_menu_button.bind('<Button-1>', self.back_to_main)
self.some_kind_of_controler = 1
self.gui_elements = [self.main_label_1,
self.main_menu_button]
def back_to_main(self, event):
if self.some_kind_of_controler == 1:
self.gui_elements_remove(self.gui_elements)
else:
pass
self.main_gui()
def gui_elements_remove(self, elements):
for element in elements:
element.destroy()
def main():
global root
root = Tk()
root.geometry('300x150+50+50')
window = MainWindow(root)
root.mainloop()
if __name__ == '__main__':
main()

Categories