How to activate tkinter window after destroying the previously one? - python-3.x

I need the next tkinter window to become active automatically after destroying the previous one.
I'm working with Python 3 in Windows 10.
import sys
from tkinter import *
#Green button pressed
def passed():
fails='0'
with open("ButtonPressed.txt",'w')as TestResult:
TestResult.write(fails)
TestResult.close()
root.destroy()
#Red button pressed
def failed():
fails='1'
with open("ButtonPressed.txt",'w')as TestResult:
TestResult.write(fails)
TestResult.close()
root.destroy()
#First window
def PushHold(UUT):
global root
root = Tk()
root.bind('<Return>', lambda q:passed())
TitleText="Push Button test"
root.title(TitleText)
root.geometry("460x160")
frame = Frame(root)
frame.pack()
bottomframe = Frame(root)
bottomframe.pack( side = BOTTOM )
LABLE_TEXT = "Push and hold S1 on "+ UUT+" board.\n Click OK."
label = Label( frame, text=LABLE_TEXT)
label.config(font=("Arial", 22))
label.pack( side = TOP)
greenbutton = Button(frame, text="OK", bg="Green", fg="White", height=2 , width = 10 , command=lambda: passed())
greenbutton.config(font=("Arial", 18))
greenbutton.pack( side = LEFT, padx=140)
root.mainloop()
#Second window
def Release(UUT):
global root
root = Tk()
root.bind('<Return>', lambda q:passed())
TitleText="Release Button test"
root.title(TitleText)
root.geometry("460x160")
frame = Frame(root)
frame.pack()
bottomframe = Frame(root)
bottomframe.pack( side = BOTTOM )
LABLE_TEXT = "Release S1 on "+ UUT+" board.\n Click OK."
label = Label( frame, text=LABLE_TEXT)
label.config(font=("Arial", 22))
label.pack( side = TOP)
greenbutton = Button(frame, text="OK", bg="Green", fg="White", height=2 , width = 10 , command=lambda: passed())
greenbutton.config(font=("Arial", 18))
greenbutton.pack( side = LEFT, padx=140)
root.mainloop()
#read results of the first window
def PushButton(UUT):
PushHold(UUT)
with open("ButtonPressed.txt",'r') as TestResult:
str = list(TestResult)
fails = int(str[0])
TestResult.close()
return fails
#read results of the second window
def ReleaseButton(UUT):
Release(UUT)
with open("ButtonPressed.txt",'r') as TestResult:
str = list(TestResult)
fails = int(str[0])
TestResult.close()
return fails
PushButton('UUT1') #first window calling
ReleaseButton('UUT1') #second window calling
The first window is working good, the second window appears, but not active. It is necessary to click on it to activate before pressing the button.
Trials to use root.withdraw() or root.lift() did not succeed.

On my system the second window takes focus without altering your code, so it is hard to tell. You could probably use root.focus_force() prior to calling root.mainloop()
Alternatively, you could spawn different windows from the same root, using tk.Toplevel.
import sys
from tkinter import *
#Green button pressed
def passed():
fails='0'
with open("ButtonPressed.txt",'w')as TestResult:
TestResult.write(fails)
TestResult.close()
root.destroy()
#Red button pressed
def failed():
fails='1'
with open("ButtonPressed.txt",'w')as TestResult:
TestResult.write(fails)
TestResult.close()
root.destroy()
#First window
def PushHold(UUT):
global root
root = Tk()
root.bind('<Return>', lambda q:passed())
TitleText="Push Button test"
root.title(TitleText)
root.geometry("460x160")
frame = Frame(root)
frame.pack()
bottomframe = Frame(root)
bottomframe.pack( side = BOTTOM )
LABLE_TEXT = "Push and hold S1 on "+ UUT+" board.\n Click OK."
label = Label( frame, text=LABLE_TEXT)
label.config(font=("Arial", 22))
label.pack( side = TOP)
greenbutton = Button(frame, text="OK", bg="Green", fg="White", height=2 , width = 10 , command=lambda: passed())
greenbutton.config(font=("Arial", 18))
greenbutton.pack( side = LEFT, padx=140)
root.focus_force() #<-------------- Here ---------------------
root.mainloop()
#Second window
def Release(UUT):
global root
root = Tk()
root.bind('<Return>', lambda q:passed())
TitleText="Release Button test"
root.title(TitleText)
root.geometry("460x160")
frame = Frame(root)
frame.pack()
bottomframe = Frame(root)
bottomframe.pack( side = BOTTOM )
LABLE_TEXT = "Release S1 on "+ UUT+" board.\n Click OK."
label = Label( frame, text=LABLE_TEXT)
label.config(font=("Arial", 22))
label.pack( side = TOP)
greenbutton = Button(frame, text="OK", bg="Green", fg="White", height=2 , width = 10 , command=lambda: passed())
greenbutton.config(font=("Arial", 18))
greenbutton.pack( side = LEFT, padx=140)
root.focus_force() #<-------------- Here ---------------------
root.mainloop()
#read results of the first window
def PushButton(UUT):
PushHold(UUT)
with open("ButtonPressed.txt",'r') as TestResult:
str = list(TestResult)
fails = int(str[0])
TestResult.close()
return fails
#read results of the second window
def ReleaseButton(UUT):
Release(UUT)
with open("ButtonPressed.txt",'r') as TestResult:
str = list(TestResult)
fails = int(str[0])
TestResult.close()
return fails
PushButton('UUT1') #first window calling
ReleaseButton('UUT1') #second window calling

Related

All other widgets are affected when one of the widgets move in a GUI (using the tkinter library in python 3)

Whenever I try to move individual widgets or click a button that produces words effectively moving other widgets that had nothing to do those both specified actions above.
Here is my code:
import tkinter as tk
# Create the main window
window = tk.Tk()
window.title("Price Calculator")
window.geometry("800x600")
window.config(background = "#777474")
def calculate_price():
global input_field
input_field_value = input_field.get()
try:
input = int(input_field_value)
price = input* 0.1
answer.config(text = (f"Your price is ","%.3f"%price,"KWD"))
except ValueError as ve:
answer.config(text = 'What you have just entered are not numbers whatsoever, try again!', fg = "#CD5F66")
price_input = tk.Label(window, text = "Total Pages:", font = "Arial", bg = "#777474", fg = "#FEFCF2")
price_input.grid(column = 0, row = 0)
input_field = tk.Entry(window, font = "Arial", bg = "#FEFCF2")
input_field.grid(column = 1, row = 0, padx = 0,pady = 10)
answer = tk.Label(window, bg = "#777474")
answer.grid(pady = 20)
button_return = tk.Button(window, text = "Calculate Price", command = calculate_price).grid()
# Run the main loop
window.mainloop()
This is my GUI before I click on the button which is called "Calculate Price":
This is my GUI after I have clicked on the button:
The problem here is that I don't want the Total Pages and the entry field to move away from each other whenever I click on the button.
I would suggest to put price_input and input_field into a frame for easier layout management. I also use sticky="w" on the frame, answer and button_return so that they are aligned at the left.
Below is the modified code:
import tkinter as tk
FGCOLOR = "#FEFCF2"
BGCOLOR = "#777474"
ERRCOLOR = "#FF5F66"
# Create the main window
window = tk.Tk()
window.title("Price Calculator")
window.geometry("800x600")
window.config(background="#777474")
def calculate_price():
input_field_value = input_field.get()
try:
input = int(input_field_value)
price = input * 0.1
answer.config(text=f"Your price is {price:.3f} KWD", fg=FGCOLOR)
except ValueError as ve:
answer.config(text='What you have just entered are not numbers whatsoever, try again!', fg=ERRCOLOR)
# create a frame for price_input and input_field
frame = tk.Frame(window, bg=BGCOLOR)
frame.grid(column=0, row=0, padx=10, pady=10, sticky="w")
price_input = tk.Label(frame, text="Total Pages:", font="Arial", bg=BGCOLOR, fg=FGCOLOR)
price_input.grid(column=0, row=0)
input_field = tk.Entry(frame, font="Arial", bg=FGCOLOR)
input_field.grid(column=1, row=0)
answer = tk.Label(window, bg=BGCOLOR)
answer.grid(column=0, row=1, padx=10, pady=10, sticky="w")
button_return = tk.Button(window, text="Calculate Price", command=calculate_price)
button_return.grid(column=0, row=2, sticky="w", padx=10, pady=10)
# Run the main loop
window.mainloop()

Make multiple tk.Toplevel windows embedded/unified in main tk window

So I'm trying to create a program which uses multiple tk.Toplevel windows. The problem with this is, that all windows show up seperated as their "own App", so when you alt tab, you switch between the toplevel windows.
The pseudocode would look something like this:
import tkinter as tk
top_levels = {}
def open_toplevel():
top_level = tk.Toplevel(root)
top_level.geometry("300x200+0+0")
top_levels.update({f"toplevel{len(top_levels.keys())}" : top_level})
root = tk.Tk()
button = tk.Button(root, command= open_toplevel)
button.place(x=0, y=0)
root.mainloop()
So my question, is: is there a way to unify them into "one window"?
If you want all of them to unify into one window then tk.Frame is a better widget to use instead of tk.Toplevel
The purpose of tk.Toplevel is to create a new temporary window, not an extra part of the window. But frames are a really good way to organise stuff.
This code below creates new frame every time you click the button. This is just a simple example. You can also use grid for widgets in a frame. I also put a border so you can see where the frames are located.
from tkinter import *
def open_frame():
frame = Frame(root, highlightbackground="black", highlightthickness=2)
lbl1 = Label(frame, text=f"Frame {len(frames) + 1} label 1")
lbl2 = Label(frame, text=f"Frame {len(frames) + 1} label 2")
lbl1.pack()
lbl2.pack()
frame.pack(padx=5, pady=5)
frames.append(frame)
root = Tk()
frames = []
btn = Button(root, text="Open Frame", command=open_frame)
btn.pack()
root.mainloop()
I hope this solution is helpful
EDIT
Use this code here to move the frames:
from tkinter import *
def open_frame():
global frame, frames
frame = Frame(root, highlightbackground="black", highlightthickness=2)
lbl1 = Label(frame, text=f"Frame {len(frames) + 1} label 1")
lbl2 = Label(frame, text=f"Frame {len(frames) + 1} label 2")
lbl1.pack()
lbl2.pack()
frame.pack(padx=5, pady=5)
frame_number = len(frames)
lbl1.bind('<B1-Motion>', lambda event: MoveWindow(event, frame_number))
lbl2.bind('<B1-Motion>', lambda event: MoveWindow(event, frame_number))
frame.bind('<B1-Motion>', lambda event: MoveWindow(event, frame_number))
frames.append(frame)
labels.append(lbl1)
labels.append(lbl2)
def MoveWindow(event, frame_number):
global root, frames
root.update_idletasks()
f = frames[frame_number]
x = f.winfo_width()/2
y = f.winfo_height()*1.5
f.place(x=event.x_root-x, y=event.y_root-y)
root = Tk()
root.geometry("500x500")
frames = []
labels = []
btn = Button(root, text="Open Frame", command=open_frame)
btn.pack()
root.mainloop()

change the position of already packed widget in tkinter

Here is the code,
from tkinter import *
root = Tk()
update_button = Button(root, text='Update')
update_button.pack()
def button():
frame1 = Frame(root)
frame1.pack()
button1 = Button(frame1, text="Button 1")
button1.pack(side=LEFT)
button2 = Button(frame1, text="Button 2")
button2.pack(side=LEFT)
button()
root.mainloop()
I want button1 to be stacked upon button2 when I click update button.
Help please.

tkinter error calling function through entries in listbox

Recently, I tried to make a full application window with a side panel menu with separate frames running some functions and submitting forms in the canvas frame.
But I found that every time I click on any entry in listbox it runs the function or method without clearing the existing one .
I tried destroy() and forget() didn't work for me (maybe I didn't know exactly how to use it?!, and the destroy() function prevent using the function again till I close the whole application and run it again!) this is a photo of my problem
this is my code :
import tkinter as tk
from tkinter import ttk
class MainWindow() :
def __init__(self,root):
# menu left
self.menu_upper_frame = tk.Frame(root, bg="#dfdfdf")
self.menu_title_label = tk.Label(self.menu_upper_frame, text="menu title", bg="#dfdfdf")
self.menu_title_label.pack()
self.menu_left_container = tk.Frame(root, width=150, bg="#ababab")
self.menu_left_upper = tk.Frame(self.menu_left_container, width=150, height=150, bg="red")
self.menu_left_upper.pack(side="top", fill="both", expand=True)
# create a listbox of items
self.Lb1 = tk.Listbox(self.menu_left_upper,bg ="red", borderwidth=0, highlightthickness=0 )
self.Lb1.insert(1, "Python")
self.Lb1.insert(2, "Perl")
self.Lb1.insert(3, "C")
self.Lb1.insert(4, "PHP")
self.Lb1.insert(5, "JSP")
self.Lb1.insert(6, "Ruby")
self.Lb1.bind("<<ListboxSelect>>", self.OnClick ) #return selected item
self.Lb1.pack(fill="both", expand=True, pady=50 )
# right area
self.inner_title_frame = tk.Frame(root, bg="#dfdfdf")
self.inner_title_label = tk.Label(self.inner_title_frame, text="inner title", bg="#dfdfdf")
self.inner_title_label.pack()
self.canvas_area = tk.Canvas(root, width=500, height=400, background="#ffffff")
self.canvas_area.grid(row=1, column=1)
# status bar
self.status_frame = tk.Frame(root)
self.status = tk.Label(self.status_frame, text="this is the status bar")
self.status.pack(fill="both", expand=True)
self.menu_upper_frame.grid(row=0, column=0, rowspan=2, sticky="nsew")
self.menu_left_container.grid(row=1, column=0, rowspan=2, sticky="nsew")
self.inner_title_frame.grid(row=0, column=1, sticky="ew")
self.canvas_area.grid(row=1, column=1, sticky="nsew")
self.status_frame.grid(row=2, column=0, columnspan=2, sticky="ew")
root.grid_rowconfigure(1, weight=1)
root.grid_columnconfigure(1, weight=1)
def OnClick(self,event):
widget = event.widget
selection = widget.curselection()
value = widget.get(selection)
if value == 'Python':
self.tabtop()
def tabtop(self):
self.tabControl = ttk.Notebook(self.canvas_area, width=400) # Create Tab Control
self.tab1 = ttk.Frame(self.tabControl) # Create a tab
self.tab2 = ttk.Frame(self.tabControl)
self.tab3 = ttk.Frame(self.tabControl)
self.tab4 = ttk.Frame(self.tabControl)
self.tab5 = ttk.Frame(self.tabControl)
self.tabControl.add(self.tab1, text='Login data' ) # Add the tab
self.tabControl.add(self.tab2, text='Permission')
self.tabControl.add(self.tab3, text='Roles')
self.tabControl.add(self.tab4, text='Personal data')
self.tabControl.add(self.tab5, text='Business data')
self.tabControl.pack(expand=1, fill="both") # Pack to make visible
self.l2 = tk.Label(self.tab2, text="label 2").pack()
self.l3 = tk.Label(self.tab3, text="label 3").pack()
root = tk.Tk()
root.title("Control Panel")
root.style = ttk.Style()
root.style.theme_use("clam")
user = MainWindow(root)
root.mainloop()
If what you're really asking is how to replace an existing notebook with a new notebook, all you need to do is call destroy() on the old notebook before creating the new one.
First, define self.tabControl to None somewhere in MainWindow.__init__. Then, in tabtop you can delete the old notebook before creating the new one:
def tabtop(self):
if self.tabControl is not None:
self.tabControl.destroy()
...

tkinter - How to set one Checkbutton opposite of other?

I am trying to set the value of one checkbox to always be the opposite of the other using tkinter (python3.5). I want it to be so that when ever the user click on one of the Checkbuttons, the other button is always changed to the opposite value.
What am I doing wrong? I cant work it out.
from tkinter import *
def opposite(buttonA):
print("running Opposite")
if buttonA.get() == 0:
buttonB.set(1)
elif buttonA.get() == 1:
buttonB.set(0)
root = Tk()
buttonA=IntVar()
buttonA.set(1)
buttonAchk = Checkbutton(root, variable=buttonA)
buttonAchk.pack()
buttonAlabel = Label(root, width=30, text="Button A")
buttonAlabel.pack()
buttonB=IntVar()
buttonB.set(0)
buttonBCheck = Checkbutton(root, variable=opposite(buttonA))
buttonBCheck.pack()
buttonBlabel = Label(root, width=30, text="Button B")
buttonBlabel.pack()
root.mainloop()
Maybe use, Radiobutton instead?
from tkinter import *
root = Tk()
buttonA=IntVar()
R1 = Radiobutton(root, text="Button A", width = 30, variable=buttonA, value=1)
R1.pack()
R2 = Radiobutton(root, text="Button B", width = 30, variable=buttonA, value=0)
R2.pack()
root.mainloop()

Resources