I'm trying to create an app that has 2 windows. The first window (A) is only called the first time the app is ran, and then opens window (B). For all future events, only window (B) is called. This is the following code:
# Script Counter/Setup
def read_counter():
if path.exists("counter.json"):
return loads(open("counter.json", "r").read()) + 1
else:
info = tk.Tk()
info.title("Setup")
info.geometry("350x120")
info.grid_columnconfigure((0, 2), weight = 1)
count = tk.Label(info, text = "Previous Post Number")
string = tk.StringVar()
count_input = tk.Entry(info, textvariable = string)
val = string.get()
def destroy_get():
val = int(count_input.get())
info.quit()
return val
count_button = tk.Button(info, text = "Done!", command = destroy_get)
tk.Label(info, text = "Setup", font='Helvetica 18 bold').grid(row = 0, column = 1, padx = 5, pady = 5)
count.grid(row = 1, column = 0, padx = 5, pady = 5)
count_input.grid(row = 1, column = 2, padx = 5, pady = 5)
count_button.grid(row = 2, column = 1, padx = 5, pady = 5)
info.mainloop()
# info.destroy()
return destroy_get()
def write_counter():
with open("counter.json", "w") as f:
f.write(dumps(counter))
counter = read_counter()
atexit.register(write_counter)
folders = ["to_post/", "not_posted/", "posted"]
for folder in folders:
if not path.exists(folder):
os.mkdir(folder)
print(os.getcwd())
# GUI
window = tk.Tk()
window.title("Confessions Bot")
window.geometry("600x350")
window.grid_columnconfigure((0,2), weight = 1)
label_tell_account = tk.Label(window, text = "Tellonym Account")
label_tell_password = tk.Label(window, text = "Tellonym Password")
label_ig_account = tk.Label(window, text = "Instagram Account")
label_ig_password = tk.Label(window, text = "Instagram Password")
tell_account = tk.Entry(window)
tell_password = tk.Entry(window)
ig_account = tk.Entry(window)
ig_password = tk.Entry(window)
image = ImageTk.PhotoImage(Image.open("logo.png"))
tk.Label(window, image = image).grid(row = 0, column = 1, padx = 10, pady = 10)
label_tell_account.grid(row = 1, column = 0)
tell_account.grid(row = 1, column = 2, padx = 10, pady = 10)
label_tell_password.grid(row = 2, column = 0, padx = 10, pady = 10)
tell_password.grid(row = 2, column = 2, padx = 10, pady = 10)
label_ig_account.grid(row = 3, column = 0, padx = 10, pady = 10)
ig_account.grid(row = 3, column = 2, padx = 10, pady = 10)
label_ig_password.grid(row = 4, column = 0, padx = 10, pady = 10)
ig_password.grid(row = 4, column = 2, padx = 10, pady = 10)
# run.grid(row = 5, column = 1, padx = 10, pady = 10)
window.mainloop()
When this is ran I get _tkinter.TclError: image "pyimage1" doesn't exist. I read that this happens since I haven't destroyed my initial window. If I change destroy_get() to have info.destroy() I'm no longer able to get the the entry from window A.
This is my first time using Tkinter and coding in general so any help is welcome.
Related
Hey I would like to create a frame which contains a Listbox and some buttons. What I would like to do is to somehow pass as an argument a name of this listbox. This is my current code in which I set the name of this listbox to master.thisListbox but I would like to pass it somehow as argument. Is it possible or should I separately crate a listbox in my App and the pass it as an argument to a frame? I'm going to create a lot of such listboxes in my App hence the name of listbox shouldn't be the same. I'm pretty new in OOP.
class myApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.dateFrame = DateFrame(self)
self.dateFrame.grid(row = 0, column = 0)
print(self.day.get())
self.myFrame = ListboxFrame(self, "Label!", [1,2,3])
self.myFrame.grid(row = 1, column = 0)
x = self.thisListbox.get(0, END)
print(x)
class DateFrame(ttk.Frame):
def __init__(self, master):
ttk.Frame.__init__(self, master)
# Day
ttk.Label(self, text = "Day", width = 4).grid(row = 0, column = 0, padx = 3, pady = 3)
master.day = IntVar(master, value = 31)
self.dayCB = ttk.Combobox(self, values = [x for x in range(1, 32)], textvariable = master.day, width = 4)
self.dayCB.grid(row = 1, column = 0, padx = 3, pady = 3)
# Month
ttk.Label(self, text = "Month", width = 6).grid(row = 0, column = 1, padx = 3, pady = 3)
self.month = IntVar(master, value = 12)
self.monthCB = ttk.Combobox(self, values = [x for x in range(1, 13)], textvariable = self.month, width = 4)
self.monthCB.grid(row = 1, column = 1, padx = 3, pady = 3)
# Year
ttk.Label(self, text = "Year", width = 4).grid(row = 0, column = 2, padx = 3, pady = 3)
self.year = IntVar(master, value = 2021)
self.yearCB = ttk.Spinbox(self, from_ = 2020, to = 2100, textvariable = self.year, width = 6)
self.yearCB.grid(row = 1, column = 2, padx = 3, pady = 3)
class ListboxFrame(ttk.Frame):
def __init__(self, master, labelText, values, selectmode = "extended", height = 6, width = 30):
ttk.Frame.__init__(self, master)
# Listbox
ttk.Label(self, text = labelText).grid(row = 0, column = 0, columnspan = 3)
master.thisListbox = tk.Listbox(self, selectmode = selectmode, height = height, width = width)
master.thisListbox.grid(row = 1, column = 0, columnspan = 3, padx = 2, pady = 2)
# Entry
self.entry = ttk.Entry(self)
self.entry.grid(row = 2, column = 0, padx = 2, pady = 2)
# Buttons
self.addButton = ttk.Button(self, text = "Add", width = 4, command = self.Add)
self.addButton.grid(row = 2, column = 1, padx = 2, pady = 2)
self.deleteButton = ttk.Button(self, text = "Delete", width = 6, command = self.Delete)
self.deleteButton.grid(row = 2, column = 2, padx = 2, pady = 2)
for v in values:
master.thisListbox.insert(END, v)
def Add(self):
if self.entry.get() == "": return
master.thisListbox.insert(END, self.entry.get())
self.entry.delete(0, END)
def Delete(self):
for index in reversed(master.thisListbox.curselection()):
master.thisListbox.delete(index)
# listbox.config(height = listbox.size())
I have a problem regarding tkinter's grid_forget() method. I have 2 pages in a notebook and I want to show certain widgets on the second page based off the user's selected options in the first page, I have a multiple choice menu and the grid_forget() method seems to work well until I select 2 or more options from the menu. I tried creating the widgets when an option is selected and place them based on the choice, no luck there, also tried creating them with the rest of the widgets and when the user selected an option I would simply just use grid to place them on the screen, also no luck there. I created a demo below, sorry for potential mistakes.
import tkinter as tk
from tkinter import ttk
SMALL_FONT = ("calibri", 16)
class App(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.notebook = ttk.Notebook(self, height = "900", width = "1600")
self.notebook.grid(row = 0, column = 0)
self.frame_pasul3 = tk.Frame(self.notebook)
self.frame_pasul1 = tk.Frame(self.notebook)
self.notebook.add(self.frame_pasul1, text = "First page")
self.notebook.add(self.frame_pasul3, text = "Second page")
self.first_page()
def first_page(self):
options = ["Urmarire mobiliara",
"Urmarire imobiliara",
"Predarea silita bunuri imobile",
"Predarea silita bunuri mobile",
"Obligatia de a face",
"Executare minori"]
menubutton_modalitate_exec = tk.Menubutton(self.frame_pasul1, text="Alegeti o modalitate de executare",
indicatoron=True, borderwidth=1, fg = "#000000",relief="raised")
menu_modalitate_exec = tk.Menu(menubutton_modalitate_exec, tearoff=False)
menubutton_modalitate_exec.configure(menu=menu_modalitate_exec)
menubutton_modalitate_exec.grid(row = 4, column = 1)
self.modalitate = {}
for choice in options:
self.modalitate[choice] = tk.StringVar()
menu_modalitate_exec.add_checkbutton(label=choice, variable=self.modalitate[choice],
onvalue=1, offvalue=0,
command=self.printValues)
self.second_page()
def second_page(self):
self.frame3_titlu_exec = ttk.Frame(self.frame_pasul3)
self.frame3_titlu_exec.grid()
self.frame3_text = ttk.Frame(self.frame_pasul3)
self.frame3_text.grid()
self.frame3_creante = tk.Frame(self.frame_pasul3)
self.frame3_creante.grid()
self.frame3_reprezentand_obligatia = tk.Frame(self.frame_pasul3)
self.frame3_judecatorie = ttk.Frame(self.frame_pasul3)
self.frame3_judecatorie.grid()
self.frame3_texte = tk.Frame(self.frame_pasul3)
self.frame3_texte.grid()
ttk.Label(self.frame3_titlu_exec, font = SMALL_FONT, text = "Titlu Executoriu").grid(row = 0, column = 0, columnspan = 4 ,pady = 10)
ttk.Button(self.frame3_titlu_exec, text = "Contract de credit.").grid(row = 1, column = 0, padx = 10, ipadx = 15, ipady = 5)
ttk.Button(self.frame3_titlu_exec, text = "Sentinta civila.").grid(row = 1, column = 1, padx = 10, ipadx = 15, ipady = 5)
ttk.Button(self.frame3_titlu_exec, text = "Contract notarial.").grid(row = 1, column = 2,padx = 10, ipadx = 15, ipady = 5)
ttk.Button(self.frame3_titlu_exec, text = "Act de adjudecare.").grid(row = 1, column = 3, padx = 10, ipadx = 15, ipady = 5)
self.entry = tk.Text(self.frame3_text, height = 2, wrap = "word", font = ("Helvetica", 10))
self.entry.grid(row = 0, column = 1, padx = 10, pady = 15)
ttk.Button(self.frame3_text, text = "Incarca titlu").grid(row = 0, column = 2, padx = 10, pady = 15)
ttk.Label(self.frame3_creante, font = SMALL_FONT, text = "Creante").grid(row = 0, column = 0)
self.btn_adauga_creante = ttk.Button(self.frame3_creante, text = "Adauga")
self.btn_adauga_creante.grid(row = 0, column = 3)
self.reprezentand_fapt_label = ttk.Label(self.frame3_judecatorie, font = SMALL_FONT, text = "Ce reprezinta fapta.")
self.reprezentand_fapt_label.grid(row = 2, column = 1)
self.reprezentand_creante = tk.Text(self.frame3_judecatorie, height = 3, width = 70)
self.reprezentand_creante.grid(row = 3 , column = 1, pady = 15)
ttk.Label(self.frame3_texte, font = SMALL_FONT, text = "Judecatorie").grid(row = 4, column = 1)
options_jud = ["optiunea 2.",
"test 3",
"test 4",
"test 5"]
self.judecatorie = ttk.Combobox(self.frame3_texte, values = options_jud)
self.judecatorie.set("Selecteaza o judecatorie.")
self.judecatorie.grid(row = 5, column = 1)
ttk.Button(self.frame3_texte, text = "Pasul 2. Parti dosar.").grid(row = 6, column = 0, padx = 15, ipadx = 15, ipady = 5)
ttk.Button(self.frame3_texte, text = "Pasul 4. Cheltuieli de executare").grid(row = 6, column = 3, ipadx = 15, ipady = 5)
def printValues(self):
for name, var in self.modalitate.items():
if var.get() == "1" and (name == "Predarea silita bunuri imobile" or name == "Predarea silita bunuri mobile" or name == "Obligatia de a face" or name == "Executare minori"):
self.reprezentand_creante_label = tk.Label(self.frame3_judecatorie, font = SMALL_FONT, text = "Ce reprezinta creanta.")
self.reprezentand_creante = tk.Text(self.frame3_judecatorie, wrap = "word", height = 3, width = 70)
self.ok_modalitate_exec = 1
self.reprezentand_creante_label.grid(row = 0, column = 1, padx = 15, pady = 15)
self.reprezentand_creante.grid(row = 1, column = 1, padx = 15, pady = 15)
print("Avem 1 la cele 4", name, var.get())
break
elif var.get() == "0" and (name == "Predarea silita bunuri imobile" or name == "Predarea silita bunuri mobile" or name == "Obligatia de a face" or name == "Executare minori"):
print("Avem 0 la cele 4", name, var.get())
self.ok_modalitate_exec = 0
self.reprezentand_creante_label.grid_forget()
self.reprezentand_creante.grid_forget()
break
if __name__ == "__main__":
main_window = tk.Tk()
app = App(main_window)
app.grid()
main_window.mainloop()
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I'm using the Scrolled Text widget in Tkinter, but when I call the destroy() method on it the Box disappears but the scroll bar stays. I provided some images so you can get a better understanding of what I'm talking about.
How can I fix this?
Here is the code, I'm talking about the item_description widget.
def add_item():
global options
global add
global remove
global display
add.config(state = "disabled", relief = "sunken")
remove.config(state = "disabled")
display.config(state = "disabled")
name_label = Label(options, text = "Item Name")
name_label.grid(row = 1, column = 0, columnspan = 3, sticky = "w")
item_name = Entry(options, width = 35)
item_name.grid(row = 2, column = 0, columnspan = 3, sticky = "w")
description_label = Label(options, text = "Item Description")
description_label.grid(row = 3, column = 0, columnspan = 3, sticky = "w")
item_description = ScrolledText(options, width = 25, height = 5)
item_description.grid(row = 4, column = 0, columnspan = 3, sticky = "w")
price_label = Label(options, text = "Item Price")
price_label.grid(row = 5, column = 0, columnspan = 3, sticky = "w")
item_price = Entry(options, width = 5)
item_price.grid(row = 6, column = 0, sticky = "w", columnspan = 3)
item_price.insert(0, "$0.00")
stock_label = Label(options, text = "Stock")
stock_label.grid(row = 7, column = 0, columnspan = 3, sticky = "w")
item_stock = Entry(options, width = 5)
item_stock.grid(row = 8, column = 0, sticky = "w", columnspan = 3)
calories_label = Label(options, text = "Calories")
calories_label.grid(row = 9, column = 0, sticky = "w", columnspan = 3)
item_calories = Entry(options, width = 5)
item_calories.grid(row = 10, column = 0, sticky = "w", columnspan = 3)
date_label = Label(options, text = "Expiry Date")
date_label.grid(row = 11, column = 0, sticky = "w", columnspan = 3)
item_expiry_date = Entry(options, width = 12)
item_expiry_date.grid(row = 12, column = 0, sticky = "w", columnspan = 3)
item_expiry_date.insert(0, "dd/mm/yyyy")
stock_add = Button(options, text = "Add", borderwidth = 2, relief = "groove",
command = lambda: add_to_stock(item_name.get(),
item_description.get("1.0", "end-1c"),
item_price.get(),
item_stock.get(),
item_calories.get(),
item_expiry_date.get()))
stock_add.grid(row = 13, column = 0, sticky = "w", columnspan = 3)
global widgets_add
widgets_add = [name_label, item_name, description_label, item_description, price_label, item_price,
stock_label, item_stock, calories_label, item_calories, date_label, item_expiry_date, stock_add]
Here is the code where I remove all the widgets from the widgets_add list, which is made at the end of the previous code.
def remove_add():
# Remove item adding dialog
global widgets_add
for widget in widgets_add:
widget.destroy()
The issue is that the ScrolledText widget actually creates
Frame
Scrollbar
ScrolledText
but only returns a reference to ScrolledText. When you destroy() that, the Frame and Scrollbar get left behind.
The easiest solution would be to add all of your controls to a Frame instance and destroy() that instead. In this way you don't have to keep track of them in a separate list.
So, assuming options is your Tk instance:
def add_item():
global options
global add
global remove
global display
add.config(state = "disabled", relief = "sunken")
remove.config(state = "disabled")
display.config(state = "disabled")
options_frame = Frame(options)
name_label = Label(options_canvas, text = "Item Name")
name_label.grid(row = 1, column = 0, columnspan = 3, sticky = "w")
item_name = Entry(options_canvas, width = 35)
item_name.grid(row = 2, column = 0, columnspan = 3, sticky = "w")
description_label = Label(options_canvas, text = "Item Description")
description_label.grid(row = 3, column = 0, columnspan = 3, sticky = "w")
item_description = ScrolledText(options_canvas, width = 25, height = 5)
item_description.grid(row = 4, column = 0, columnspan = 3, sticky = "w")
price_label = Label(options_canvas, text = "Item Price")
price_label.grid(row = 5, column = 0, columnspan = 3, sticky = "w")
item_price = Entry(options_canvas, width = 5)
item_price.grid(row = 6, column = 0, sticky = "w", columnspan = 3)
item_price.insert(0, "$0.00")
stock_label = Label(options_canvas, text = "Stock")
stock_label.grid(row = 7, column = 0, columnspan = 3, sticky = "w")
item_stock = Entry(options_canvas, width = 5)
item_stock.grid(row = 8, column = 0, sticky = "w", columnspan = 3)
calories_label = Label(options_canvas, text = "Calories")
calories_label.grid(row = 9, column = 0, sticky = "w", columnspan = 3)
item_calories = Entry(options_canvas, width = 5)
item_calories.grid(row = 10, column = 0, sticky = "w", columnspan = 3)
date_label = Label(options_canvas, text = "Expiry Date")
date_label.grid(row = 11, column = 0, sticky = "w", columnspan = 3)
item_expiry_date = Entry(options_canvas, width = 12)
item_expiry_date.grid(row = 12, column = 0, sticky = "w", columnspan = 3)
item_expiry_date.insert(0, "dd/mm/yyyy")
stock_add = Button(options_canvas, text = "Add", borderwidth = 2, relief = "groove",
command = lambda: add_to_stock(item_name.get(),
item_description.get("1.0", "end-1c"),
item_price.get(),
item_stock.get(),
item_calories.get(),
item_expiry_date.get()))
stock_add.grid(row = 13, column = 0, sticky = "w", columnspan = 3)
def remove_add():
# Remove item adding dialog
global options_frame
options_frame.destroy()
I made small medical calculator program for python learning.
In this program, when i press "Calc" button, it should be displayed in my command line. But it doesn't work.
Moreover, I suspect that the defined function is operated without button click.
What do i have a mistake?
#importing modules
from tkinter import *
#setting up window
top = Tk()
F = Frame(top)
F.master.title("FeNa Calculator")
F.pack()
#Calc. button event handler
def fena_click():
ur_na = tUNa.get()
ur_cr = tUCr.get()
se_na = tSNa.get()
se_cr = tSCr.get()
print('Urine Na : ' + ur_na, end=' ')
print('Urine Cr : ' + ur_cr, end=' ')
print('Serum Na : ' + se_na, end=' ')
print('Serum Cr : ' + se_cr, end=' ')
#add widgets
unit1 = Label(F, text="mEq/L")
unit2 = Label(F, text="mEq/L")
unit3 = Label(F, text="mEq/L")
unit4 = Label(F, text="mEq/L")
UNa = Label(F, text="Urine Na")
tUNa = Entry(F)
UCr = Label(F, text="Urine Cr")
tUCr = Entry(F)
SNa = Label(F, text="Serum Na")
tSNa = Entry(F)
SCr = Label(F, text="Serum Cr")
tSCr = Entry(F)
blank1 = Label(F, text="")
v_Result = StringVar()
Result = Label(F, textvariable = v_Result)
v_Result.set("FENa(%) = ")
blank2 = Label(F, text="")
bCalc = Button(F, text="Calc.", command = fena_click())
bQuit = Button(F, text="Quit", command = F.quit)
UNa.grid(row = 0, column = 0, pady = 2)
tUNa.grid(row =0, column = 1, pady = 2)
unit1.grid(row = 0, column = 2, pady = 2)
UCr.grid(row = 1, column = 0, pady = 2)
tUCr.grid(row =1, column = 1, pady = 2)
unit2.grid(row = 1, column = 2, pady = 2)
SNa.grid(row = 2, column = 0, pady = 2)
tSNa.grid(row =2, column = 1, pady = 2)
unit3.grid(row = 2, column = 2, pady = 2)
SCr.grid(row = 3, column = 0, pady = 2)
tSCr.grid(row =3, column = 1, pady = 2)
unit4.grid(row = 3, column = 2, pady = 2)
blank1.grid(row=4, column = 0, columnspan = 3)
Result.grid(row = 5, column = 0, columnspan = 3)
blank2.grid(row=6, column = 0, columnspan = 3)
bCalc.grid(row = 7, column = 0, columnspan = 2)
bQuit.grid(row = 7, column = 1, columnspan = 2)
#loop running
F.mainloop()
Program view
In the line where you're making the button, you are actually calling the fena_click function. You need to pass the function itself, which you can do by omitting the paranthesis:
bCalc = Button(F, text="Calc.", command = fena_click) # no () after fena_click
I am trying to call a variable or a StringVar from the class called GUI without calling the GUI as the object of the class Conversion. Here is an example of my code:
class GUI:
def __init__(self,root):
c = Conversion(measurements,measurements1,Text_Legnth_Left,Text_Length_Right)
measurements = self.measurements
measurements1 = self.measurements1
Text_Length_Left = self.Text_Legnth_Left
Text_Length_Right = self.Text_Length_Right
self.notebook = ttk.Notebook(root)
self.notebook.pack()
self.length_frame = ttk.Frame(self.notebook)
self.weight_frame = ttk.Frame(self.notebook)
self.temperature_frame = ttk.Frame(self.notebook)
self.notebook.add(self.length_frame, text = 'Length')
#Combobox
self.measurements = StringVar()
self.Combobox_Length_Left = ttk.Combobox(self.length_frame, textvariable = self.measurements, values = ('mm', 'cm', 'inch', 'ft', 'yd', 'm', 'km', 'mi'), width = 10,state=['readonly'])
self.Combobox_Length_Left.current(5)
self.measurements.trace('w', c.update_length())
self.Combobox_Length_Left.grid(row = 2, column = 0, padx = 5, pady = 5, sticky = E)
self.measurements1 = StringVar()
self.Combobox_Length_Right = ttk.Combobox(self.length_frame, textvariable = self.measurements1, value = ('mm', 'cm', 'inch', 'ft', 'yd', 'm', 'km', 'mi'), width = 10,state = ['readonly'])
self.Combobox_Length_Right.current(5)
self.measurements1.trace('w', c.self.update_length())
self.Combobox_Length_Right.grid(row = 2, column = 2, padx = 5, pady = 5, sticky = E)
#Labels
self.Conversion = ttk.Label(self.length_frame, text = 'Conversion:').grid(row = 1, column = 0, padx = 5, pady = 5, sticky = W)
self.Label_Blank = ttk.Label(self.length_frame, text = '').grid(row = 1, column = 1, padx = 5, pady = 5, sticky = E)
self.Label_To2 = ttk.Label(self.length_frame, text = 'to').grid(row = 2, column = 1, padx = 5, pady = 5, sticky = E)
self.Label_To = ttk.Label(self.length_frame, text = 'to').grid(row = 3, column = 1, padx = 5, pady = 5, sticky = E)
#Entry Boxes
self.Text_Length_Left = StringVar()
self.Entry_Length_Left = ttk.Entry(self.length_frame, textvariable = self.Text_Length_Left,width = 13)
self.Text_Length_Left.trace('w', self.update_length)
self.Entry_Length_Left.grid(row = 3, column = 0, padx = 5, pady = 5)
self.Text_Length_Right = StringVar()
self.Entry_Length_Right = ttk.Entry(self.length_frame, textvariable = self.Text_Length_Right,width = 13, state='readonly')
And here is my other class:
class Conversion:
def __init__(self,measurements,measurements1,Text_Legnth_Left,Text_Length_Right):
g = GUI(measurements,measurements1,Text_Legnth_Left,Text_Length_Right)
as_meter = dict(mm=0.001, cm=0.01, inch=0.0254,ft=0.3048, yd=0.9144, m=1.0,km=1000.0, mi=1609.344,)
def update_length(self, *args,g):
try:
v = int(g.self.Text_Length_Left.get())
except ValueError:
g.self.Text_Length_Left.set('')
g.self.Text_Length_Right.set('')
return
m = v * self.as_meter [g.self.measurements.get()]
r = m/self.as_meter[g.self.measurements1.get()]
g.self.Text_Length_Right.set("{:.5g}".format(r))
My attempt of calling the the variables such as measurements was c=Conversion(measurements) I know by doing class GUI(Conversion) will work and make it its object but I can't do it for specific reasons.
Thanks for any help really appreciate it!