How to implement lift method? - python

I am trying to move my function NEW_FRAME in front of the Frame for the root window so that old frame and the other widget in it will be behind for the function NEW_FRAME to only display its widget. So I searched and discovered that tkinter has lift method to achieve that but I can't implement it correctly, have tried positioning it at different places inside the function.
this link :explanation of the lift method with an example
from tkinter import *
root = Tk()
root.geometry("1300x600")
welcome = Frame(root, bg="yellow")
welcome.pack( fill=BOTH, expand=True)
label = Label(welcome, text="welcome bro to page one")
label.grid(row=45, column=50)
b = Label(welcome, text="you can select menu bar to switch page")
b.grid(row=100, column=500)
def NEWS_Frame():
new = Frame(root, bg="red")
new.pack(fill=BOTH, expand=True)
l1 = Label(new, text="Have been waiting for")
l1.grid(row=49, column=80)
l2 = Label(new, text="hello dude how be things")
l2.grid(row=0, column=0)
new.lift() # have position it to lift the new frame to the top of Frame
# menu bar start here
MAIN_MENU = Menu(root)
root.config(menu=MAIN_MENU)
File_menu = Menu(MAIN_MENU)
MAIN_MENU.add_cascade(label="NEW PAGE", menu=File_menu, underline=0)
File_menu.add_command(label="NEWS", command=NEWS_Frame)
root.mainloop()

First of all, your Minimal, Complete, and Verifiable example should only include the least amount of code as possible to reproduce the specific issue. The code below reproduces exactly the behavior you're having an issue with, but nothing more:
import tkinter as tk
def swap():
button2.pack()
button2.lift()
if __name__ == '__main__':
root = tk.Tk()
button1 = tk.Button(root, text="Swap with button 2", command=swap)
button2 = tk.Button(root, text="Swap with button 1")
button1.pack()
root.mainloop()
A workaround using pack:
You can't put widgets over another widget using pack. pack is literally for stacking in the 2-d, as in it is for stacking horizontally or vertically but not for piling widgets in the depth dimension. However, a bad workaround would be to simply hide the widget while displaying the other, which doesn't require lift at all.
In the below code each time swap is called it hides one button while displaying the other:
try: # In order to be able to import tkinter for
import tkinter as tk # either in python 2 or in python 3
except:
import Tkinter as tk
def swap():
global is_button1_lifted
if is_button1_lifted:
button1.pack_forget()
button2.pack()
else:
button2.pack_forget()
button1.pack()
is_button1_lifted = not is_button1_lifted
if __name__ == '__main__':
root = tk.Tk()
is_button1_lifted = True
button1 = tk.Button(root, text="Swap with button 2", command=swap)
button2 = tk.Button(root, text="Swap with button 1", command=swap)
swap()
root.mainloop()
Answer using grid:
This is the way of using lift in the OP's case. The way this works is that both widgets displayed in the same node of a grid. The widget lift method is used on simply comes over the other(s).
In the below example both buttons are displayed, while one(button2 in this case) simply blocks the other by being in front of the other. When the lift is called it simply makes its object come to the front:
try: # In order to be able to import tkinter for
import tkinter as tk # either in python 2 or in python 3
except:
import Tkinter as tk
def swap():
global is_button1_lifted
if is_button1_lifted:
button2.lift()
else:
button1.lift()
is_button1_lifted = not is_button1_lifted
if __name__ == '__main__':
root = tk.Tk()
is_button1_lifted = False
button1 = tk.Button(root, text="Swap with button 2", command=swap)
button2 = tk.Button(root, text="Swap with button 1", command=swap)
button1.grid(row=0, column=0)
button2.grid(row=0, column=0)
root.mainloop()
Answer using place:
This works almost the same way as the answer with grid, place simply has a more direct layout control:
try: # In order to be able to import tkinter for
import tkinter as tk # either in python 2 or in python 3
except:
import Tkinter as tk
def swap():
global is_button1_lifted
if is_button1_lifted:
button2.lift()
else:
button1.lift()
is_button1_lifted = not is_button1_lifted
if __name__ == '__main__':
root = tk.Tk()
is_button1_lifted = False
button1 = tk.Button(root, text="Swap with button 2", command=swap)
button2 = tk.Button(root, text="Swap with button 1", command=swap)
button1.place(x=23, y=87)
button2.place(x=23, y=87)
root.mainloop()

lift moves widgets in the Z axis, pack arranges widgets in the X and Y axis. lift is incapable of changing the ordering of widget arranged with pack

Related

Unable to display buttons on the right hand side of the tkinter GUI

I'm trying to create a 800x800 GUI where on left hand side I need a treeview to later display data from MySQL, and on right hand side, I am struggling to display five buttons "Read Excel", "Invoice Per Order", "Save PDF", and "Close". Treeview is showing but no one button is visible at the moment. What should I do?
Here is my code:
import tkinter as tk
from tkinter import ttk
# Create the root window
root = tk.Tk()
root.geometry("800x800")
# Create the treeview
treeview = ttk.Treeview(root)
treeview.pack(side="left", fill="both", expand=True)
# Create the buttons
read_excel_button = tk.Button(root, text="Read Excel")
invoice_per_order_button = tk.Button(root, text="Invoice per Order")
save_pdf_button = tk.Button(root, text="Save PDF")
close_button = tk.Button(root, text="Close")
# Place the buttons in a frame and pack the frame to the right of the root window
button_frame = tk.Frame(root)
button_frame.pack(side="right", fill="both")
read_excel_button.pack(side="top", in_=button_frame)
invoice_per_order_button.pack(side="top", in_=button_frame)
save_pdf_button.pack(side="top", in_=button_frame)
close_button.pack(side="top", in_=button_frame)
# Run the Tkinter event loop
root.mainloop()
You are using duplicated between line 18-25. You don't needed frame for pack()
Easier for you:
import tkinter as tk
from tkinter import ttk
# Create the root window
root = tk.Tk()
root.geometry("800x800")
# Create the treeview
treeview = ttk.Treeview(root)
treeview.pack(side="left", fill="both", expand=True)
# Create the buttons
read_excel_button = tk.Button(root, text="Read Excel").pack()
invoice_per_order_button = tk.Button(root, text="Invoice per Order").pack()
save_pdf_button = tk.Button(root, text="Save PDF").pack()
close_button = tk.Button(root, text="Close").pack()
# Run the Tkinter event loop
root.mainloop()
Output:
it works by removing parameters from .pack() methods on each button.
button_frame = tk.Frame(root)
button_frame.pack(side="right", fill="both")
read_excel_button.pack()
invoice_per_order_button.pack()
save_pdf_button.pack()
close_button.pack()

Swaping between frames on tkinter Python

I want to create an app that starts on a main window and by pressing a button it should change to a diferent tkinter frame so the main frame should not be visible. The problem I have is that one frame overlaps another and I can see labels which shouldnt appear (labels of the main frame)
This is what I see on the main window:
Main window
and this is what I see when I press the button:
I just want to have the "Win 2" label
This is the code I have:
import tkinter
root = tkinter.Tk()
root.title("My Program")
root.geometry("700x350")
def swap_window():
win2 = tkinter.Frame(root).grid()
tag2 = tkinter.Label(win2, text="Win 2").grid(row=0, column=0)
main_window = tkinter.Frame(root).grid()
main_tag = tkinter.Label(main_window, text="Main window").grid(row=0, column=0)
btn_swap_window = tkinter.Button(main_window, text="Window 2", command=swap_window).grid(row=1, column=0)
root.grid()
root.mainloop()

Dictionary within a function passing values to another function

I am having an issue with my code. I am relatively new at coding. My issue is that I am trying to take the dictionary SeatingOrder populated in the Waitlist.GuestList function and then pass those values, if there are any, to the Staff function so that I can display them in a drop-down and modify them. I can't seem to find a way to do it and any help or even a point in the right direction would be helpful.
import math
from tkinter import *
import time
#initializes time based on system time
count= int(0)
t= time.localtime()
current_Time = float(time.strftime("%H%M%S", t))
SeatingOrder = {''}
root=Tk()
root.title("Main Screen")
root.geometry("1920x1080")
def WaitList():
#tnikter screen setup
root=Tk()
root.title("Seating List")
root.geometry("1920x1080")
#creates label and entry box
PartyName = Entry(root)
PartyName.grid(row=0, column=1)
Label(root,text="Enter the party name: ").grid(row=0, column=0)
#creates label and entry box
PartySize = Entry(root)
PartySize.grid(row=0, column=3)
Label(root, text="How many are in your party? ").grid(row=0, column=2)
#creates a dictionary with an array inside of it so information can be search by the key value
SeatingOrder = {PartyName : [PartySize, current_Time]}
#defintion to populate array
def GuestList():
x = str(PartyName.get())
y = int(PartySize.get())
SeatingOrder = {x : [y, current_Time]}
#Prints statement and displays the result
Label(root, text="Your spot has been saved!").grid(row=3, column=1)
Label(root, text=SeatingOrder).grid(row=3, column=2)
#creates a button the runs the command.
Button(root, text="Save", command=GuestList).grid(row=1, column=1)
Button(root, text="x", command=root.destroy).grid(row=1, column=10)
root.mainloop()
return SeatingOrder
def Staff():
Dictionary = WaitList()
root=Tk()
root.title("Administration")
root.geometry("1920x1080")
def show():
Label(root, Text=clicked.get()).grid(row=1, column=1)
clicked = StringVar()
clicked.set("Please select a party")
SeatingDropDown = OptionMenu(root, clicked, )
SeatingDropDown.grid(row=0, column=1)
Button(root, text="select", command=show).grid(row=0, column=2)
Button(root, text="x", command=root.destroy).grid(row=1, column=10)
exit
Button(root, text="Waitlist", command=WaitList).grid(row=5, column=1)
Button(root, text="Staff", command=Staff).grid(row=5, column=2)
root.mainloop()
Just one point is that in this code you have set up a root main screen window and for each function you have set up a new root window (note that Staff window has no mainloop call and so wouldn't have an event loop)
But I would scrap all that. The usual way with tkinter is to have a root (Main screen) and all subsequent windows are made tkinter.Toplevel with the root as master. Skeleton example for just this point:
import tkinter as tk
root - tk.Tk()
root.geometry('1920x1080+0+0') # geometry is 'widthxheight+x+y'
WaitListwindow = tk.Toplevel(root)
WaitListwindow.pack()
WaitListwindow.place(x=10,y=10) #place values are now relative to the root geometry
Staffwindow = tk.Toplevel(root)
Staffwindow.pack()
Staffwindow.place(x=70,y=10)
root.mainloop()
now root is the parent\master and WaitListWindow and StaffWindow are the children. Note that I use pack and place but grid applies just as well with the appropriate parameters.
You can then place the buttons and entry as children of the appropraite window, eg
staffselectb = tk.Button(Staffwindow)
staffselectb.pack()
staffselectb.place(x=5,y=5) # this button is now relative to Staffwindow placement
#so that x and y are inside Staffwindow at (5,5)
With the root.mainloop() you can now bind events to a widget, eg to retrieve the Entry widget contents.
There is more but I just wanted to concentrate on this point.

Python Tkinter simple value process

I just new for the GUI and need little help.
a=int(input())
if a==0:
print("hi")
else:
print("hello")
I want to change input process to click button, like a switch.
left button -> a=0
right button -> a=1
window=tkinter.Tk()
window.title("")
window.geometry("640x640+100+100")
window.resizable(True, True)
a=tkinter.Button(window, text="left")
a.pack()
b=tkinter.Button(window, text="right")
b.pack()
window.mainloop()
I can see left, right button but I don't know how to put values.
Is there any example I can use?
Thanks
Does this example help You:
from tkinter import Tk, Button
def switch(btn1, btn2):
btn1.config(state='disabled')
btn2.config(state='normal')
print(btn1['text'])
window = Tk()
window.title("")
on = Button(window, text="On", command=lambda: switch(on, off))
on.pack(side='left', expand=True, fill='x')
off = Button(window, text="Off", command=lambda: switch(off, on))
off.pack(side='left', expand=True, fill='x')
off.config(state='disabled')
window.mainloop()
If You have questions ask but here is pretty good site to look up tkinter widgets and what they do, their attributes.
Also I suggest You follow PEP 8
You need to add a function to each one that will be executed when the buttons are clicked like this:
import tkinter as tk
def left_clicked():
print("Left button clicked")
right_button.config(state="normal") # Reset the button as normal
left_button.config(state="disabled") # Disable the button
def right_clicked():
print("Right button clicked")
right_button.config(state="disabled")
left_button.config(state="normal")
window = tk.Tk()
window.title("")
window.geometry("640x640+100+100")
# window.resizable(True, True) # Unneeded as it is already the default
left_button = tk.Button(window, text="left", command=left_clicked)
left_button.pack(side="left")
right_button = tk.Button(window, text="right", command=right_clicked,
state="disabled")
right_button.pack(side="right")
window.mainloop()

How to compulsory close message box for Toplevel window

image for that
I have few lines of code here which is login system which works fine but i can click on the Toplevel button multiple times when i provide the wrong password without closing the messagebox.How can i make it so that it has to be closed messagebox before i can make attempt again.
from tkinter import *
from tkinter import messagebox
def top():
if entry1.get() == "333":
log.destroy()
root.deiconify()
else:
messagebox.showerror("error", "try again")
root = Tk()
root.geometry("300x300")
log = Toplevel(root)
log.geometry("200x200")
label1 = Label(log, text="password")
entry1 = Entry(log)
button1 = Button(log, text="login", command=top)
label1.pack()
entry1.pack()
button1.pack(side="bottom")
lab = Label(root, text="welcome bro").pack()
root.withdraw()
root.mainloop()
You need to make the log window the parent of the dialog:
messagebox.showerror("error", "try again", parent=log)
By default it will use the root window (the Tk instance) as the parent which in this case is not what you want.
With hint from #furas this how to implement this:
create another function to the call it when the entry doesn't match and use grab_set method for the Toplevel window tp.grab_set().You can add your customarised image to the Toplevel window as well as message to display in the box(here: i use label to depict that)
from tkinter import *
from tkinter import messagebox
def dialog(): # this function to call when entry doesn't match
tp = Toplevel(log)
tp.geometry("300x100")
tp.title('error')
tp.grab_set() # to bring the focus to the window for you to close it
tp.resizable(width=False, height=False)
l = Label(tp, text="try again\n\n\n\n add your customarize image to the window")
l.pack()
def top():
if entry1.get() == "333":
log.destroy()
root.deiconify()
else:
dialog() # being called here
root = Tk()
root.geometry("300x300")
log = Toplevel(root)
log.geometry("200x200")
label1 = Label(log, text="password")
entry1 = Entry(log)
button1 = Button(log, text="login", command=top)
label1.pack()
entry1.pack()
button1.pack(side="bottom")
lab = Label(root, text="welcome bro").pack()
root.withdraw()
root.mainloop()

Categories