How change tkinter Notebook tab and keep configuration? - python

I have a gui with two tabs and would like to switch back and forth between the tabs while keeping the content of the tabs. If I do this all in one function, then it works fine, but since I have more in the individual functions. I have outsourced them. Now I have bound the individual functions to the tabs. But here I have the problem that I overwrite the tabs with every change. But I would like to switch between the tabs without overwriting the entries. I understand why I overwrite the input. After all, I call the individual functions with rountine and overwrite them that way. Unfortunately I do not know how to do it better.
import tkinter as tk
from tkinter import ttk
class display():
def __init__(self):
self.root = tk.Tk()
self.root.geometry('400x300')
self.root.title('Notebook Demo')
def gui(self):
# create a notebook
self.notebook = ttk.Notebook(self.root)
self.notebook.place(rely=0.0, relheight=1, relwidth=1)
# create frames
self.frame1 = ttk.Frame(self.notebook, width=400, height=280)
self.frame2 = ttk.Frame(self.notebook, width=400, height=280)
self.frame1.place(rely=0.0, relheight=1, relwidth=1)
self.frame2.place(rely=0.0, relheight=1, relwidth=1)
# add frames to notebook
self.notebook.add(self.frame1, text='General Information')
self.notebook.add(self.frame2, text='Profile')
self.notebook.bind("<<NotebookTabChanged>>", self.routine)
self.gu1()
self.root.update_idletasks()
self.root.mainloop()
def routine(self,event):
if self.notebook.index("current") == 1:
self.gu1()
else:
self.gu2()
def gu1(self):
button1 = tk.Button(self.frame1, text="test1", command=self.changeText)
button1.grid(column=0, row=0)
self.label1 = tk.Label(self.frame1, text="test1")
self.label1.grid(column=1, row=0)
self.root.mainloop()
def gu2(self):
button2 = tk.Button(self.frame2, text="test2", command=self.changeText2)
button2.grid(column=0, row=0)
self.label2 = tk.Label(self.frame2, text="test2")
self.label2.grid(column=1, row=0)
self.root.mainloop()
def changeText(self):
self.label1["text"] = "change1"
def changeText2(self):
self.label2["text"] = "change2"
if __name__ == "__main__":
display().gui()

All problem is that you use .gu1() and .gu2() in routine().
You should run .gu1() and .gu2() only once - at start in gui().
def gui(self):
# ... code ...
self.notebook.bind("<<NotebookTabChanged>>", self.routine)
self.gu1() # create at start
self.gu2() # create at start
def routine(self,event):
if self.notebook.index("current") == 1:
#self.gu1() # DON'T DO THIS
print('selected tab 1')
else:
#self.gu2() # DON'T DO THIS
print('selected tab 2')
Working code:
tkinter should use only one mainloop()
import tkinter as tk
from tkinter import ttk
class display():
def __init__(self):
self.root = tk.Tk()
self.root.geometry('400x300')
self.root.title('Notebook Demo')
def gui(self):
# create a notebook
self.notebook = ttk.Notebook(self.root)
self.notebook.place(rely=0.0, relheight=1, relwidth=1)
# create frames
self.frame1 = ttk.Frame(self.notebook, width=400, height=280)
self.frame2 = ttk.Frame(self.notebook, width=400, height=280)
self.frame1.place(rely=0.0, relheight=1, relwidth=1)
self.frame2.place(rely=0.0, relheight=1, relwidth=1)
# add frames to notebook
self.notebook.add(self.frame1, text='General Information')
self.notebook.add(self.frame2, text='Profile')
self.notebook.bind("<<NotebookTabChanged>>", self.routine)
self.gu1()
self.gu2()
self.root.update_idletasks()
self.root.mainloop()
def routine(self,event):
if self.notebook.index("current") == 1:
#self.gu1() # DON'T DO THIS
print('selected tab 1')
else:
#self.gu2() # DON'T DO THIS
print('selected tab 2')
def gu1(self):
button1 = tk.Button(self.frame1, text="test1", command=self.changeText)
button1.grid(column=0, row=0)
self.label1 = tk.Label(self.frame1, text="test1")
self.label1.grid(column=1, row=0)
def gu2(self):
button2 = tk.Button(self.frame2, text="test2", command=self.changeText2)
button2.grid(column=0, row=0)
self.label2 = tk.Label(self.frame2, text="test2")
self.label2.grid(column=1, row=0)
def changeText(self):
self.label1["text"] = "change1"
def changeText2(self):
self.label2["text"] = "change2"
if __name__ == "__main__":
display().gui()
EDIT:
If you have to create some widgets in tabs with delays (ie. to wait for user's values in other widgets) then you should use boolean variables (True/False) to run it only once in routine()
def gui(self):
# ... code ...
self.gu1_created = False
self.gu2_created = False
self.notebook.bind("<<NotebookTabChanged>>", self.routine)
def routine(self,event):
if self.notebook.index("current") == 1:
if not self.gu1_created:
self.gu1()
self.gu1_created = True
print('selected tab 1')
else:
if not self.gu2_created:
self.gu2()
self.gu2_created = True
print('selected tab 2')

Related

I can not figure out why my app menu is still freezing after I have used threading on tkinter

When I run the app, the run button is still responsive for a few seconds before the entire app freezes but the thread continues running. Where is the problem in my code and how do fix it?
import threading
from tkinter import *
from tkinter import ttk
class SubExtractor:
def __init__(self, root):
self.root = root
self._create_layout()
def _create_layout(self):
self.root.title("Sub Extractor")
self._menu_bar()
self.main_frame = ttk.Frame(self.root, padding=(5, 5, 5, 15))
self._video_frame()
self._progress_frame()
self._output_frame()
self.main_frame.grid()
def _menu_bar(self):
self.root.option_add('*tearOff', FALSE)
menubar = Menu(self.root)
self.root.config(menu=menubar)
menu_file = Menu(menubar)
menu_settings = Menu(menubar)
menubar.add_cascade(menu=menu_file, label="File")
menubar.add_cascade(menu=menu_settings, label="Settings")
menu_file.add_command(label="Open", command=self._open_file)
menu_file.add_command(label="Close", command=self._close_window)
menu_settings.add_command(label="Language", command=self._language_settings)
menu_settings.add_command(label="Extraction", command=self._extraction_settings)
def _video_frame(self):
video_frame = ttk.Frame(self.main_frame, borderwidth=2, relief="ridge", width=1000, height=600)
video_frame.grid()
def _progress_frame(self):
progress_frame = ttk.Frame(self.main_frame)
progress_frame.grid(row=1, sticky="W")
self.run_button = ttk.Button(progress_frame, text="Run", command=self._run)
self.run_button.grid(pady=10, padx=30)
self.progress_bar = ttk.Progressbar(progress_frame, orient=HORIZONTAL, length=800, mode='determinate')
self.progress_bar.grid(column=2, row=0)
def _output_frame(self):
output_frame = ttk.Frame(self.main_frame)
output_frame.grid(row=2)
self.text_output_widget = Text(output_frame, width=97, height=12, state="disabled")
self.text_output_widget.grid()
output_scroll = ttk.Scrollbar(output_frame, orient=VERTICAL, command=self.text_output_widget.yview)
output_scroll.grid(column=1, row=0, sticky="N,S")
self.text_output_widget.configure(yscrollcommand=output_scroll.set)
def _close_window(self):
self._stop_run()
self.root.quit()
def _stop_run(self):
self.interrupt = True
self.run_button.configure(text="Run", command=self._run)
def _text_to_output(self, text):
self.text_output_widget.configure(state="normal")
self.text_output_widget.insert("end", f"{text}\n")
self.text_output_widget.see("end")
self.text_output_widget.configure(state="disabled")
def long_running_method(self):
num = 100000
self.progress_bar.configure(maximum=num)
for i in range(0, num):
if self.interrupt:
break
self._text_to_output(f"Line {i} of {num}")
self.progress_bar['value'] += 1
self._stop_run()
def _run(self):
self.interrupt = False
self.run_button.configure(text='Stop', command=self._stop_run)
threading.Thread(target=self.long_running_method).start()
rt = Tk()
SubtitleExtractorGUI(rt)
rt.mainloop()
What I expect to accomplish is for the loop to insert texts in the text widget while I can still freely move and use other buttons on the app.

Modules and classes in Python for a desktop application

This is to be a desktop application for opening multiple small databases and running queries on them. So far I've written some code for opening forms as necessary. Is this a good way to do it? Also - the code shown opens two copies of each form - what am I doing wrong? It's my first attempt at Python and I'm a rudimentary programmer so simple answers would be of most help please. TIA (Python 3.9.6)
link_1.py
from tkinter import Tk
import link_2
root = Tk()
class ClassLink_1:
#if another function in the class is called, the __init__ function is run at start up
def __init__(self):
print("in link_1 __init__ instruction")
#the call_function function can be called at start up, or not, and will act accordingly
def call_function(self):
print("in call_function")
#the line below is run at start up whether or not another function in the class is called
print("in link_1")
root.withdraw() #hides the blank form at start up
#if __name__ == "__main__":
#the line below shows the link_2 form, whether or not the if __name__==__main__ condition is used as its condition
link_2.ClassLink_2(root).__init__(root)
#link_3.ClassLink_3(root).__init__(root)
#the line below runs call_function on start up to print text
ClassLink_1().call_function()
root.mainloop()
link_2.py
from tkinter import Tk, Button
from tkinter import * #for Toplevel
import link_3
root = Tk()
class ClassLink_2:
def __init__(self, master):
self.openNewWindow()
def openNewWindow(self):
newWindow = Toplevel(root) #creates a top level widget with the parent root (first parameter)
newWindow.title("Title opened from link_1")
newWindow.geometry("500x500")
label = Label(newWindow, text ="Opened from link_1").grid(row=1, column=1)
self.add_button = Button(newWindow, text="in ClassLink_2", command= self.do_add)
self.add_button.grid(row=3, column=1)
def do_add(self):
print("button pressed")
link_3.ClassLink_3(root).__init__(root)
root.withdraw() #hides the blank form at start up
link_3.py
from tkinter import Tk, Button
from tkinter import * #for Toplevel
root = Tk()
class ClassLink_3:
def __init__(self, master):
self.openNewWindow()
def openNewWindow(self):
newWindow = Toplevel(root) #creates a top level widget with the parent root (first parameter)
newWindow.title("Title opened from link_2")
newWindow.geometry("500x500")
label = Label(newWindow, text ="Opened from link_2").grid(row=1, column=1)
self.add_button = Button(newWindow, text="in ClassLink_3", command= self.do_add)
self.add_button.grid(row=3, column=1)
def do_add(self):
print("button pressed")
# link_4.ClassLink_4(root).__init__(root) this file has not yet been made
root.withdraw() #hides the blank form at start up
This is a proposed solution, can be expanded as needed. Constructive suggestions for improvement of the structure or code would be appreciated. TIA. I've left in the details in case they are of use to anyone.
link_1
from tkinter import Tk
import link_2
root = Tk()
class ClassLink_1:
def __init__(self):
print("in link_1 __init__ instruction")
root.withdraw() #hides the blank form at start up
link_2.ClassLink_2(root).openNewWindow(0)
root.mainloop()
link_2
from tkinter import Tk, Button
from tkinter import *
import link_3
root = Tk()
class ClassLink_2:
root.withdraw() #hides the blank form at start up
class_var_1 = 0
inst_var_1 = 0
def __init__(self, incoming_inst_var_1):
pass
def openNewWindow(self, inst_var_1_to_open):
newWindow = Toplevel(root)
newWindow.title("Title opened from link_1")
newWindow.geometry("500x500")
label = Label(newWindow, text ="Opened from link_1").grid(row=1, column=1)
self.add_button = Button(newWindow, text="in ClassLink_2", command= self.do_add)
self.add_button.grid(row=3, column=1)
self.add_button = Button(newWindow, text="increment class_var_1", command= self.inc_class_var_1)
self.add_button.grid(row=5, column=1)
self.inst_var_1 = inst_var_1_to_open
def do_add(self):
print("button pressed")
link_3.ClassLink_3(root).openNewWindow(0)
def inc_class_var_1(self):
ClassLink_2.class_var_1 += 2
self.inst_var_1 += 1
print("self.class_var_1 = " + (str)(self.class_var_1))
print("self.inst_var_1 = " + (str)(self.inst_var_1))
link_3
from tkinter import Tk, Button
from tkinter import *
from tkinter.ttk import Combobox
import tkinter.scrolledtext as tkscrolled
# import link_4 <filename of next form>
root = Tk()
class ClassLink_3:
class_var_1 = 0
inst_var_1 = 0
# ------------------------------- START CLASS CONTROLS -----------------------------
root.withdraw()
def __init__(self, incoming_inst_var_1):
pass
def openNewWindow(self, inst_var_1_to_open):
new_window = Toplevel(root)
self.widget_factory(new_window)
self.inst_var_1 = inst_var_1_to_open
def do_add(self):
print("button pressed")
# link_4.ClassLink_4(root).openNewWindow(0) # <filename of next form>
# ---------------------------------- END CLASS CONTROLS -----------------------------
# -------------------------------------- START CALCS --------------------------------------
def inc_class_var_1(self):
ClassLink_3.class_var_1 += 2
self.inst_var_1 += 1
print("self.class_var_1 = " + (str)(self.class_var_1))
print("self.inst_var_1 = " + (str)(self.inst_var_1))
# ---------------------------------------- END CALCS --------------------------------------
# ---------------------------------------- START FACTORY SHOPS-----------------------------------------
def widget_factory(self, new_window):
self.shop_window(new_window)
self.shop_labels(new_window)
self.shop_buttons(new_window)
self.shop_menu(new_window)
self.shop_listbox(new_window)
self.shop_combobox(new_window)
self.shop_radiobuttons(new_window)
self.shop_checkbuttons(new_window)
self.shop_entries(new_window)
self.shop_canvas(new_window)
self.shop_scale(new_window)
self.shop_scrollbars(new_window)
self.shop_textbox(new_window)
self.shop_menu(new_window)
pass
# ------------------------
def shop_window(self, new_window):
new_window.title("Title opened from link_2")
new_window.geometry("800x900")
def shop_labels(self, new_window):
self.label_1 = Label(new_window, text ="Opened from link_2").grid(row=1, column=1)
def shop_buttons(self, new_window):
self.button_1 = Button(new_window, text="in ClassLink_3", command= self.do_add)
self.button_1.grid(row=3, column=1)
self.button_2 = Button(new_window, text="increment class_var_1", command= self.inc_class_var_1)
self.button_2.grid(row=5, column=1)
def shop_listbox(self, new_window):
data=("one", "two", "three", "four")
self.listbox_1 = Listbox(new_window, height=5, selectmode='multiple')
for num in data:
self.listbox_1.insert(END,num)
self.listbox_1.grid(row=7, column=1)
def shop_combobox(self, new_window):
data=("one", "two", "three", "four")
self.combobox_1 = Combobox(new_window, values=data)
self.combobox_1.grid(row=8, column=3)
def shop_radiobuttons(self, new_window):
var_1 = IntVar()
var_1.set(1)
self.rad_btn_1 = Radiobutton(new_window, text="male", variable=var_1, value=1)
self.rad_btn_2 = Radiobutton(new_window, text="female", variable=var_1, value=2)
self.rad_btn_1.grid(row=9, column=1)
self.rad_btn_2.grid(row=9, column=2)
def shop_checkbuttons(self, new_window):
var_1 = IntVar()
var_2 = IntVar()
self.checkbtn_1 = Checkbutton(new_window, text = "Cricket", variable = var_1)
self.checkbtn_2 = Checkbutton(new_window, text = "Tennis", variable = var_2)
self.checkbtn_1.grid(row=10, column=1)
self.checkbtn_2.grid(row=10, column=2)
def shop_entries(self, new_window):
self.entry_1 = Entry(new_window, width = 20)
self.entry_1.insert(0,'Username')
self.entry_1.grid(row= 11, column=2)
self.entry_2 = Entry(new_window, width = 15)
self.entry_2.insert(0,'password')
self.entry_2.grid(row= 12, column=2)
#might want to place on a frame, see example https://coderslegacy.com/python/list-of-tkinter-widgets/
def shop_canvas(self, new_window):
canvas = Canvas(new_window, bg= 'white', width = 260,height = 260) #this is the background for the figure
# left and top of figure is from [x from left, y from top] of canvas right and bottom of figure from [x from left, y from top] of canvas
coordinates = 20, 50, 210, 230
arc = canvas.create_arc(coordinates, start=0, extent=250, fill="blue") #start is from E, extent is in degrees CCW
arc = canvas.create_arc(coordinates, start=250, extent=50, fill="red")
arc = canvas.create_arc(coordinates, start=300, extent=60, fill="yellow")
canvas.grid(row=2, column=1)
def shop_scale(self, new_window):
self.scale_1 = Scale(new_window, from_=0, to=10, orient=VERTICAL)
self.scale_1.grid(row=15, column=2)
self.scale_2 = Scale(new_window, from_=0, to=10, orient = HORIZONTAL)
self.scale_2.grid(row=15, column=3)
def shop_scrollbars(self, new_window):
self.scroll_vert = Scrollbar(new_window)
self.scroll_vert.grid(row=19, column=3)
self.listbox_3 = Listbox(new_window, yscrollcommand = self.scroll_vert.set )
for line in range(1, 100):
self.listbox_3.insert(END, "Number " + str(line))
self.listbox_3.grid(row=19 , column=2)
self.scroll_vert.config(command = self.listbox_3.yview)
def shop_textbox(self, new_window):
#make a frame with parent new_window
self.frame_textbox_1 = Frame(new_window)
self.frame_textbox_1.grid(row=1, column=5)
#make the textbox with parent frame
self.textbox_1 = Text(self.frame_textbox_1)
self.textbox_1.config(wrap=NONE, width=15, height=8) #width, height are characters x rows permitted wrap values should be WORD CHAR, or NONE
#make the X scrollbar with parent frame
self.scroll_text_horiz = Scrollbar(self.frame_textbox_1, orient="horizontal")
self.scroll_text_horiz.config(command = self.textbox_1.xview)
#make the Y scrollbar with parent frame
self.scroll_text_vert = Scrollbar(self.frame_textbox_1, orient="vertical")
self.scroll_text_vert.config(command = self.textbox_1.yview)
#pack the scrollbars before the texbox to allow them to fill the frame width and height
self.scroll_text_horiz.pack(side=BOTTOM, fill=X)
self.scroll_text_vert.pack(side=RIGHT, fill=Y)
self.textbox_1.pack(fill="y")
#connect the scrollbars to the textbox
self.textbox_1["xscrollcommand"] = self.scroll_text_horiz.set
self.textbox_1["yscrollcommand"] = self.scroll_text_vert.set
message = "the quick brown fox"
self.textbox_1.insert(1.1, message)
# ----------------------------------------------
def shop_menu(self, new_window):
print("in shop menu1")
menubar = Menu(new_window)
print("in shop_menu2")
file = Menu(menubar, tearoff=0)
file.add_command(label="New")
file.add_command(label="Open")
file.add_command(label="Save")
file.add_command(label="Save as...")
file.add_command(label="Close")
file.add_separator()
file.add_command(label="Exit", command=new_window.quit)
menubar.add_cascade(label="File", menu=file)
edit = Menu(menubar, tearoff=0)
edit.add_command(label="Undo")
edit.add_separator()
edit.add_command(label="Cut")
edit.add_command(label="Copy")
edit.add_command(label="Paste")
edit.add_command(label="Delete")
edit.add_command(label="Select All")
menubar.add_cascade(label="Edit", menu=edit)
help = Menu(menubar, tearoff=0)
help.add_command(label="About")
menubar.add_cascade(label="Help", menu=help)
new_window.config(menu=menubar)
print("in shop menu3")
# --------------------------------------- END FACTORY SHOPS---------------------------------------

Python - Tkinter - invisible text in ttk.Entry in sub window

I'm trying to make a sub window for configuration settings. But the text in the sub window is invisible. I am reading correctly but I cannot see the text. Below is my sample code with the problem:
import tkinter as tk
from tkinter import ttk
from tkinter import Menu
class Frames:
def __init__(self):
self.port_com = None
def main_frame(self, win):
# Main Frame
main = ttk.LabelFrame(win, text="")
main.grid(column=0, row=0, sticky="WENS", padx=10, pady=10)
return main
def dut_configuration_frame(self, win):
# Configuration Frame
dut_config_frame = ttk.LabelFrame(win, text="Config")
dut_config_frame.grid(column=0, row=0, sticky='NWS')
# Port COM
ttk.Label(dut_config_frame, text="Port COM").grid(column=0, row=0)
self.port_com = tk.StringVar()
ttk.Entry(dut_config_frame, width=12, textvariable=self.port_com).grid(column=0, row=1, sticky=tk.EW)
self.port_com.set(value="COM7")
print(self.port_com.get())
class ConfigFrames:
def __init__(self):
self.port_com = None
def main_frame(self, win):
# Main Frame
main = ttk.LabelFrame(win, text="")
main.grid(column=0, row=0, sticky="WENS", padx=10, pady=10)
return main
def configuration_frame(self, win):
# Configuration Frame
dut_config_frame = ttk.LabelFrame(win, text="Config")
dut_config_frame.grid(column=0, row=0, sticky='NWS')
# Port COM
ttk.Label(dut_config_frame, text="Port COM").grid(column=0, row=0)
self.port_com = tk.StringVar()
ttk.Entry(dut_config_frame, width=12, textvariable=self.port_com).grid(column=0, row=1, sticky=tk.EW)
self.port_com.set(value="COM5")
print(self.port_com.get())
def menu_bar(win):
def _config():
config_frame = ConfigFrames()
config_window = tk.Tk()
config_window.title("Sub window")
config_window.geometry("200x200")
config_window.resizable(0, 0)
main = config_frame.main_frame(config_window)
config_frame.configuration_frame(main)
config_window.mainloop()
# Menu
menuBar = Menu(win)
win.config(menu=menuBar)
settingsMenu = Menu(menuBar, tearoff=0)
settingsMenu.add_command(label="Config", command=_config)
menuBar.add_cascade(label="Settings", menu=settingsMenu)
frames = Frames()
win = tk.Tk()
win.title("Main window")
win.geometry("200x200")
win.resizable(0, 0)
menu_bar(win)
main = frames.main_frame(win)
frames.dut_configuration_frame(win)
win.mainloop()
As you can see in main window it is visible, but in sub window it is invisible.
And printing in console is correct:

Clearing the screen in Tkinter

I have tried all the other posts on this topic but none of them have worked for me...
Here is my code:
from tkinter import *
window=Tk()
window.geometry('600x400')
window.title('hello world')
def wrong():
root=Tk()
text=Text(root)
text.insert(INSERT,"WRONG!, you stupid idiot!!!!")
text.pack()
def right():
root=Tk()
text=Text(root)
text.insert(INSERT,"CORRECT, good job!")
text.pack()
def reset():
hide_widgets()
class UIProgram():
def setupUI(self):
buttonlist=[]
button= Button(window,text='Sanjam',command=wrong).pack()
button2=Button(window,text='Sunny the Bunny',command=wrong).pack()
button3= Button(window, text='Sunjum',command=right).pack()
button4= Button(window, text='bob',command=wrong).pack()
button5= Button(window, text='next',command=reset)
button5.pack()
self.label=Label(window)
self.label.pack()
window.mainloop()
program= UIProgram()
program.setupUI()
I am aware of pack_forget() and tried it, but it keeps giving me an error. Also, is it possible to make a command(like the 'reset' one I have) and use that in the command for a clear screen button. Please help, I am new to Tkinter and don't know much about these things..
Thanks
Example code
I'm tired to describe the same mistakes hundreds of times - some comments in code.
import tkinter as tk
# --- classes ---
class UIProgram():
def __init__(self, master):
self.master = master # use to add elements directly to main window
self.buttons = [] # keep buttons to change text
# frame to group buttons and easily remove all buttons (except `Next`)
self.frame = tk.Frame(self. master)
self.frame.pack()
# group button in frame
button = tk.Button(self.frame, text='Sanjam', command=self.wrong)
button.pack()
self.buttons.append(button)
button = tk.Button(self.frame, text='Sunny the Bunny', command=self.wrong)
button.pack()
self.buttons.append(button)
button = tk.Button(self.frame, text='Sunjum', command=self.right)
button.pack()
self.buttons.append(button)
button = tk.Button(self.frame, text='bob', command=self.wrong)
button.pack()
self.buttons.append(button)
# button outside frame
button_next = tk.Button(self.master, text='Next >>', command=self.reset)
button_next.pack()
self.label = tk.Label(self.frame)
self.label.pack()
def wrong(self):
# create second window with message and closing button
win = tk.Toplevel()
tk.Label(win, text="WRONG!, you stupid idiot!!!!").pack()
tk.Button(win, text='close', command=win.destroy).pack()
def right(self):
# create second window with message and closing button
win = tk.Toplevel()
tk.Label(win, text="CORRECT, good job!").pack()
tk.Button(win, text='close', command=win.destroy).pack()
def reset(self):
# remove frame with all buttons
self.frame.pack_forget()
tk.Label(self.master, text="frame removed").pack()
# or only remove text in labels
#for button in self.buttons:
# button['text'] = '-- place for new text --'
# --- main ---
root = tk.Tk()
root.geometry('600x400')
root.title('hello world')
program = UIProgram(root)
root.mainloop()
BTW: if you do var = Widget(...).pack() then you assign None to var because pack()/grid()/place() return None. You have to do it in two lines
var = Widget(...)
var.pack()
or in one line if you don't need var
Widget(...).pack()

Python tkinter checkbutton value not accessible

I want to build a little GUI application in Python. The goal is to have a main window calling several other windows. In one of these called windows I have a checkbutton. My problem is that I cannot read the value of this checkbutton, whereas I can read the value of an Entry widget. What am I doing wrong?
from tkinter import *
import tkinter as tk
class mainwindow():
def __init__(self, master):
self.master = master
menubalk = Menu(self.master)
menubalk.add_command(label="New window", command=self.openNewwindow)
self.master.config(menu=menubalk)
def openNewwindow(self):
window = newwindow()
window.mainloop()
class newwindow(Tk):
def __init__(self):
Tk.__init__(self)
self.var = BooleanVar()
self.checkbutton = Checkbutton(self, text="Check", variable=self.var)
self.checkbutton.grid(column=0, row=0)
self.var2 = StringVar()
self.entry = Entry(self, textvariable=self.var2)
self.entry.grid(column=2,row=0)
self.button2 = Button(self,text=u"Show", command=self.showValues).grid(column=1, row=0)
def showValues(self):
print('Value checkbutton:', self.var.get(), ';', 'Value entryfield: ', self.entry.get())
def main():
root = Tk()
window = mainwindow(root)
root.mainloop()
if __name__ == '__main__':
main()
You are making multiple, separate Tkinter applications in your program. Do not do that. To create new windows, use the Toplevel widget.
from tkinter import *
class mainwindow():
def __init__(self, master):
self.master = master
menubalk = Menu(self.master)
menubalk.add_command(label="New window", command=self.openNewwindow)
self.master.config(menu=menubalk)
def openNewwindow(self):
def showValues(var, entry):
print('Value checkbutton:', var.get(), ';', 'Value entryfield: ', entry.get())
window = Toplevel(self.master)
var = BooleanVar()
checkbutton = Checkbutton(window, text="Check", variable=var)
checkbutton.grid(column=0, row=0)
var2 = StringVar()
entry = Entry(window, textvariable=var2)
entry.grid(column=2,row=0)
button2 = Button(window,text=u"Show", command=lambda: showValues(var, entry))
button2.grid(column=1, row=0)
def main():
root = Tk()
window = mainwindow(root)
root.mainloop()
if __name__ == '__main__':
main()
Tkinter's variable objects (IntVar, StringVar, etc.) must take argument "master" as their firs parameter. i.e. replace
self.var=StringVar()
With
self.var=StringVar(self)
Or
self.var=StringVar(master=self)

Categories

Resources