Related
Every time I click on the buttons I get a error. Could anyone help me by providing a fix or telling me what the issue was because I cant see the issue.
Whenever the button is clicked it is supposed to open a new page and the side bar on the left with the buttons in should stay where they are at.
import tkinter
import tkinter.messagebox
import customtkinter
customtkinter.set_appearance_mode("dark")
customtkinter.set_default_color_theme("dark-blue")
class App(customtkinter.CTk):
def __init__(self):
super().__init__()
# configure window
self.title("Opium")
self.geometry(f"{1100}x{580}")
# configure grid layout (4x4)
self.grid_columnconfigure(1, weight=1)
self.grid_columnconfigure((2, 3), weight=0)
self.grid_rowconfigure((0, 1, 2), weight=1)
# create sidebar frame with widgets
self.content_label = customtkinter.CTkLabel(self, text="", font=customtkinter.CTkFont(size=30, weight="bold"))
self.content_label.grid(row=0, column=1, rowspan=4, sticky="nsew", padx=(10, 0), pady=(20, 10))
self.sidebar_frame = customtkinter.CTkFrame(self, width=140, corner_radius=0)
self.sidebar_frame.grid(row=0, column=0, rowspan=4, sticky="nsew")
self.sidebar_frame.grid_rowconfigure(4, weight=1)
self.logo_label = customtkinter.CTkLabel(self.sidebar_frame, text="Opium", font=customtkinter.CTkFont(size=30, weight="bold"))
self.logo_label.grid(row=0, column=0, padx=20, pady=(20, 10))
self.sidebar_button_1 = customtkinter.CTkButton(self.sidebar_frame, text="Button 1", command=self.sidebar_button_event)
self.sidebar_button_1.grid(row=1, column=0, padx=20, pady=10)
self.sidebar_button_2 = customtkinter.CTkButton(self.sidebar_frame, text="Button 2", command=self.sidebar_button_event)
self.sidebar_button_2.grid(row=2, column=0, padx=20, pady=10)
self.sidebar_button_3 = customtkinter.CTkButton(self.sidebar_frame, text="Button 3", command=self.sidebar_button_event)
self.sidebar_button_3.grid(row=3, column=0, padx=20, pady=10)
self.appearance_mode_label = customtkinter.CTkLabel(self.sidebar_frame, text="Appearance Mode:", anchor="w")
self.appearance_mode_label.grid(row=5, column=0, padx=20, pady=(10, 0))
self.appearance_mode_optionemenu = customtkinter.CTkOptionMenu(self.sidebar_frame, values=["Light", "Dark", "System"],
command=self.change_appearance_mode_event)
self.appearance_mode_optionemenu.grid(row=6, column=0, padx=20, pady=(10, 10))
def open_input_dialog_event(self):
dialog = customtkinter.CTkInputDialog(text="Type in a number:", title="CTkInputDialog")
print("CTkInputDialog:", dialog.get_input())
def change_appearance_mode_event(self, new_appearance_mode: str):
customtkinter.set_appearance_mode(new_appearance_mode)
def change_scaling_event(self, new_scaling: str):
new_scaling_float = int(new_scaling.replace("%", "")) / 100
customtkinter.set_widget_scaling(new_scaling_float)
def sidebar_button_event(self):
try:
self.right_frame.destroy()
except AttributeError:
pass
self.right_frame = customtkinter.CTkFrame(self, bg="white", width=900, height=580)
self.right_frame.grid(row=0, column=1, rowspan=3, columnspan=2, sticky="nsew")
self.home_label = customtkinter.CTkLabel(self.right_frame, text="Home", font=customtkinter.CTkFont(size=30, weight="bold"), bg="white")
self.home_label.pack(side="top", fill="both", padx=20, pady=20)
if __name__ == "__main__":
app = App()
app.mainloop()
I have tested the code and the error you are getting when clicking the buttons is
ValueError: ['bg'] are not supported arguments. Look at the documentation for supported arguments.
As the error already says, bg is not a supported argument by customtkinter.
https://github.com/TomSchimansky/CustomTkinter/wiki/CTkLabel#arguments
In your specific case you have to change the two instances of bg="white" to bg_color="white".
import tkinter
import tkinter.messagebox
import customtkinter
customtkinter.set_appearance_mode("dark")
customtkinter.set_default_color_theme("dark-blue")
class App(customtkinter.CTk):
def __init__(self):
super().__init__()
# configure window
self.title("Opium")
self.geometry(f"{1100}x{580}")
# configure grid layout (4x4)
self.grid_columnconfigure(1, weight=1)
self.grid_columnconfigure((2, 3), weight=0)
self.grid_rowconfigure((0, 1, 2), weight=1)
# create sidebar frame with widgets
self.content_label = customtkinter.CTkLabel(
self, text="", font=customtkinter.CTkFont(size=30, weight="bold"))
self.content_label.grid(
row=0, column=1, rowspan=4, sticky="nsew", padx=(10, 0), pady=(20, 10))
self.sidebar_frame = customtkinter.CTkFrame(
self, width=140, corner_radius=0)
self.sidebar_frame.grid(row=0, column=0, rowspan=4, sticky="nsew")
self.sidebar_frame.grid_rowconfigure(4, weight=1)
self.logo_label = customtkinter.CTkLabel(
self.sidebar_frame, text="Opium", font=customtkinter.CTkFont(size=30, weight="bold"))
self.logo_label.grid(row=0, column=0, padx=20, pady=(20, 10))
self.sidebar_button_1 = customtkinter.CTkButton(
self.sidebar_frame, text="Button 1", command=self.sidebar_button_event)
self.sidebar_button_1.grid(row=1, column=0, padx=20, pady=10)
self.sidebar_button_2 = customtkinter.CTkButton(
self.sidebar_frame, text="Button 2", command=self.sidebar_button_event)
self.sidebar_button_2.grid(row=2, column=0, padx=20, pady=10)
self.sidebar_button_3 = customtkinter.CTkButton(
self.sidebar_frame, text="Button 3", command=self.sidebar_button_event)
self.sidebar_button_3.grid(row=3, column=0, padx=20, pady=10)
self.appearance_mode_label = customtkinter.CTkLabel(
self.sidebar_frame, text="Appearance Mode:", anchor="w")
self.appearance_mode_label.grid(row=5, column=0, padx=20, pady=(10, 0))
self.appearance_mode_optionemenu = customtkinter.CTkOptionMenu(self.sidebar_frame, values=["Light", "Dark", "System"],
command=self.change_appearance_mode_event)
self.appearance_mode_optionemenu.grid(
row=6, column=0, padx=20, pady=(10, 10))
def open_input_dialog_event(self):
dialog = customtkinter.CTkInputDialog(
text="Type in a number:", title="CTkInputDialog")
print("CTkInputDialog:", dialog.get_input())
def change_appearance_mode_event(self, new_appearance_mode: str):
customtkinter.set_appearance_mode(new_appearance_mode)
def change_scaling_event(self, new_scaling: str):
new_scaling_float = int(new_scaling.replace("%", "")) / 100
customtkinter.set_widget_scaling(new_scaling_float)
def sidebar_button_event(self):
try:
self.right_frame.destroy()
except AttributeError:
pass
self.right_frame = customtkinter.CTkFrame(
self, bg_color="white", width=900, height=580)
self.right_frame.grid(row=0, column=1, rowspan=3,
columnspan=2, sticky="nsew")
self.home_label = customtkinter.CTkLabel(
self.right_frame, text="Home", font=customtkinter.CTkFont(size=30, weight="bold"), bg_color="white")
self.home_label.pack(side="top", fill="both", padx=20, pady=20)
if __name__ == "__main__":
app = App()
app.mainloop()
For the next time please be so kind and include the error message you are getting with your question
I am creating a Calculator application with Tkinter, and I've included all the useful buttons there. But the problem is whenever I resize my Tkinter window to a custom size using geometry() method, all buttons don't scale up in the same ratio. To be precise, the buttons in the first column strech a lot leaving other buttons the same size they were. Is there a way to fix all this because it has become harder to include more things in the default size.
Here are some images:
Without custom geometry-
With custom geometry (800x800)-
Here's the useful bit of code:
root = Tk()
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
root.resizable(False, False)
segoe_font = tkFont.Font(family='Segoe UI', size=16)
segoe_font_ac = tkFont.Font(family='Segoe UI', size=8)
entry_text = StringVar()
inout = Entry(root, textvariable=entry_text)
inout.grid(row=0, column=0, columnspan=4, sticky="nsew")
button18 = Button(root, text="AC", command=allclear, font=segoe_font_ac).grid(row=1, column=0, sticky="nsew")
button1 = Button(root, text="C", command=clear, font=segoe_font).grid(row=1, column=1, sticky="nsew")
button2 = Button(root, text="/", command=divide, font=segoe_font).grid(row=1, column=2, sticky="nsew")
button3 = Button(root, text="×", command=multiply, font=segoe_font).grid(row=1, column=3, sticky="nsew")
button5 = Button(root, text="7", command=tsev, font=segoe_font).grid(row=2, column=0, sticky="nsew")
button6 = Button(root, text="8", command=teig, font=segoe_font).grid(row=2, column=1, sticky="nsew")
button7 = Button(root, text="9", command=tnin, font=segoe_font).grid(row=2, column=2, sticky="nsew")
button4 = Button(root, text="-", command=minus, font=segoe_font).grid(row=2, column=3, sticky="nsew")
button9 = Button(root, text="4", command=tfou, font=segoe_font).grid(row=3, column=0, sticky="nsew")
button10 = Button(root, text="5", command=tfiv, font=segoe_font).grid(row=3, column=1, sticky="nsew")
button11 = Button(root, text="6", command=tsix, font=segoe_font).grid(row=3, column=2, sticky="nsew")
button8 = Button(root, text="+", command=plus, font=segoe_font).grid(row=3, column=3, sticky="nsew")
button12 = Button(root, text="1", command=tone, font=segoe_font).grid(row=4, column=0, sticky="nsew")
button13 = Button(root, text="2", command=ttwo, font=segoe_font).grid(row=4, column=1, sticky="nsew")
button14 = Button(root, text="3", command=tthr, font=segoe_font).grid(row=4, column=2, sticky="nsew")
button15 = Button(root, text="=", command=equals, font=segoe_font).grid(row=4, column=3, rowspan=2, sticky="nsew")
button16 = Button(root, text="0", command=tzer, font=segoe_font).grid(row=5, column=0, columnspan=2, sticky="nsew")
button17 = Button(root, text=".", command=decimal, font=segoe_font).grid(row=5, column=2, sticky="nsew")
entry_text.trace("w", lambda *args: character_limit_and_check_entered_value(entry_text))
root.mainloop()
Can anyone help?
When you resize a window, the grid geometry manager will allocate extra space to every row and every column that has a non-zero weight. The weight is proportional, so a column with a weight of 2 will get twice as many of the extra pixels as a column with a weight of 1. By default, all columns have a weight of zero.
If you want every column or row to be given a percentage of extra available space, you need to give them a non-zero weight. If you want the columns or rows to have an identical width or height you can use the uniform option. All rows or columns with the same uniform value will be of a uniform height or width.
Since you explicitly gave a non-zero weight to only the first row and the first column, that row and column is going to be allocated all extra space. This is why the top entry widget grows in width and height, and all of the buttons in the first column grow in width.
In your case I'm guessing you want the top entry widget to stay the same height, while all of the buttons expand equally. To do that, remove your existing calls to rowconfigure and columnconfigure and replace them with the following:
root.grid_rowconfigure((1,2,3,4,5), weight=1, uniform="row")
root.grid_columnconfigure((0,1,2,3), weight=1, uniform="column")
I think this will help you. I made simple example with 6 buttons but I think you will manage to do it for your case. So I think best option is to use Grid.rowconfigure and Grid.columnconfigure funcitons.
Example code:
from tkinter import *
root = Tk()
root.title("resize button")
root.geometry("500x500")
# here you need to put on what do you want to use row configure, index(row) and weight
Grid.rowconfigure(root, 0, weight=1) # we use on root, row=0 weight=1
Grid.columnconfigure(root, 0, weight=1)
#configure 2nd row
Grid.rowconfigure(root, 1, weight=1)
#configure 3rd row
Grid.rowconfigure(root, 2, weight=1)
#configure 2nd column
Grid.columnconfigure(root, 1, weight=1)
button1 = Button(root, text="Button1")
button2 = Button(root, text="Button2")
button3 = Button(root, text="Button3")
button1.grid(row=0, column=0, sticky="nsew")
button2.grid(row=1, column=0, sticky="nsew")
button3.grid(row=2, column=0, sticky="nsew")
button1_1 = Button(root, text="Button1_1")
button2_1 = Button(root, text="Button2_1")
button3_1 = Button(root, text="Button3_1")
button1_1.grid(row=0, column=1, sticky="nsew")
button2_1.grid(row=1, column=1, sticky="nsew")
button3_1.grid(row=2, column=1, sticky="nsew")
root.mainloop()
Now buttons are resizing with canvas.
in my GUI I used two panedwindow widgets with two inside frames for each of them. All works as I axpected, except the resizing.. when I resize the frames, all widgets start to flick, and I really don't like to see it.
To understand better the issue, I took a piece of code from my real program and I simplified it as much as possible:
from tkinter import *
from tkinter import ttk
class MainWindow:
def __init__(self):
# main window:
self.parent=Tk()
self.parent.geometry("760x620+370+100")
self.parent.title("Main Window")
self.parent.configure(background="#f0f0f0")
self.parent.minsize(760, 600)
self.Frame1=PanedWindow(self.parent, orient=HORIZONTAL)
self.Frame1.grid(row=0, column=0, padx=(5,4), pady=(6,0), sticky="nswe")
self.parent.grid_columnconfigure(0, weight=1)
self.parent.grid_rowconfigure(0, weight=1)
self.Frame1_1=Frame(self.Frame1)
self.Frame1_1.pack(side=LEFT)
self.Frame1_2=Frame(self.Frame1)
self.Frame1_2.pack(side=RIGHT)
self.Frame1_1.grid_columnconfigure(0, weight=1)
self.Frame1_1.grid_rowconfigure(0, weight=1)
# Frame1_1:
self.Frame1_1_1=PanedWindow(self.Frame1_1, orient=VERTICAL)
self.Frame1_1_1.grid(row=0, column=0, sticky="nswe")
self.MainNotebook=ttk.Notebook(self.Frame1_1_1)
self.MainNotebook.pack(fill=BOTH, expand=True)
self.MainNotebookFrame=Frame(self.MainNotebook, background="white")
self.MainNotebookFrame.pack()
self.MainNotebook.add(self.MainNotebookFrame, text="Tab1")
self.Search1SV=StringVar()
self.Search1Entry=ttk.Entry(self.MainNotebookFrame, textvariable=self.Search1SV)
self.Search1Entry.pack(fill=BOTH, padx=5, pady=5)
self.TVDFrame=Frame(self.MainNotebookFrame, background="white", highlightbackground="#7a7a7a", highlightthickness=1)
self.TVDFrame.pack(fill=BOTH, expand=True, padx=5, pady=(0,4))
self.TVDFrame.grid_columnconfigure(1, weight=1)
self.TVDFrame.grid_rowconfigure(1, weight=1)
self.TreeView1=ttk.Treeview(self.TVDFrame, height=10, selectmode="browse")
self.TreeView1.grid(row=0, column=0, columnspan=3, rowspan=3, sticky="nsew")
self.HeaderFrame=Frame(self.TVDFrame, height=25, background="#d9ebf9")
self.HeaderFrame.grid(row=0, column=0, columnspan=3, sticky="nsew")
ttk.Label(self.HeaderFrame, text="Languages:", background="#d9ebf9").grid(row=0, column=0, pady=3)
self.TreeView1SBY=ttk.Scrollbar(self.TVDFrame, orient="vertical", command=self.TreeView1.yview)
self.TreeView1SBY.grid(row=0, column=2, rowspan=2, sticky="nse")
self.TreeView1.configure(yscroll=self.TreeView1SBY.set)
self.TreeView1.insert("", "end", text="Ciao")
self.TreeView1.insert("", "end", text="Hola")
self.TreeView1.insert("", "end", text="привет")
Frame(self.TVDFrame, height=1, width=4, background="white", highlightthickness=0, highlightbackground="white").grid(row=0, column=0, columnspan=3, sticky="new")
Frame(self.TVDFrame, height=1, width=4, background="white", highlightthickness=0, highlightbackground="white").grid(row=2, column=0, columnspan=3, sticky="ew")
Frame(self.TVDFrame, width=1, height=4, background="white", highlightthickness=0, highlightbackground="white").grid(row=0, column=0, rowspan=3, sticky="ns")
self.SecondNotebookFrame=Frame(self.Frame1_1_1)
self.SecondNotebookFrame.pack(fill=BOTH)
self.SecondNotebook=ttk.Notebook(self.SecondNotebookFrame)
self.SecondNotebook.pack(fill=BOTH, expand=True, pady=(2,1))
self.OptionalFrame1=Frame(self.SecondNotebook, background="white")
self.OptionalFrame1.pack()
self.SecondNotebook.add(self.OptionalFrame1, text="Tab1")
self.OptionalFrame2=Frame(self.OptionalFrame1, background="white", highlightbackground="#7a7a7a", highlightthickness=1)
self.OptionalFrame2.pack(fill=BOTH, expand=True, padx=5, pady=(5,4))
self.PBFrame1=Frame(self.Frame1_1, background="white", highlightbackground="#d9d9d9", highlightthickness=1)
self.PBFrame1.grid(row=1, column=0, padx=(1,3), pady=(3,1), sticky="nswe")
self.PBFrame2=Frame(self.PBFrame1, background="white", highlightbackground="#7a7a7a", highlightthickness=1)
self.PBFrame2.pack(fill=BOTH, padx=5, pady=5)
self.Progressbar=ttk.Progressbar(self.PBFrame2, mode="determinate", maximum=100, value=0)
self.Progressbar.pack(fill=BOTH, padx=10, pady=10)
# frame Frame1_2:
self.WorkNotebook=ttk.Notebook(self.Frame1_2)
self.WorkNotebook.pack(fill=BOTH, expand=True, pady=(1,0))
self.WorkNotebookFrame=Frame(self.WorkNotebook, background="white")
self.WorkNotebookFrame.pack()
self.WorkNotebook.add(self.WorkNotebookFrame, text="Tab1")
self.WorkNotebookFrame=Frame(self.WorkNotebookFrame, background="white", highlightbackground="#7a7a7a", highlightthickness=1)
self.WorkNotebookFrame.pack(fill=BOTH, expand=True, padx=5, pady=(5,4))
self.PBFrame1=Frame(self.Frame1_1, background="white", highlightbackground="#d9d9d9", highlightthickness=1)
self.PBFrame1.grid(row=1, column=0, padx=(1,3), pady=(3,1), sticky="nswe")
self.PBFrame2=Frame(self.PBFrame1, background="white", highlightbackground="#7a7a7a", highlightthickness=1)
self.PBFrame2.pack(fill=BOTH, padx=5, pady=5)
self.Progressbar=ttk.Progressbar(self.PBFrame2, mode="determinate", maximum=100, value=0)
self.Progressbar.pack(fill=BOTH, padx=10, pady=10)
self.Frame1.add(self.Frame1_1, minsize=230)
self.Frame1.add(self.Frame1_2, minsize=250)
self.Frame1_1_1.add(self.MainNotebook, minsize=56)
self.Frame1_1_1.add(self.SecondNotebookFrame, minsize=104)
# end:
self.parent.mainloop()
if __name__=="__main__":
app=MainWindow()
in addition I attached also a GIF and this image shows exactly when the issue happen:
how can I solve the resizing issue?
I have a grid placing a top, center, and footer frames, then I'm making frames inside the Center frame (I'll call them subframes as I don't know what to refer to them as). When I try to pack/grid/place a button inside the subframes it won't work. If I grid the buttons, they appear at the bottom of all top-level frames which doesn't make any sense to me since I put them in their appropriate subframes... This is really hard to explain, but that's the best I can do.
from tkinter import messagebox
import math
# gui
root = tk.Tk()
root.title('Bid Generator')
root.geometry('{}x{}'.format(800, 880))
# main containers
top_frame = tk.Frame(root, bg='#00c3ff', height=75)
center = tk.Frame(root, bg='white')
footer = tk.Frame(root, bg='black', height=100)
# layout of the main containers
root.grid_rowconfigure(1, weight=1)
root.grid_columnconfigure(0, weight=1)
top_frame.grid(row=0, sticky="ew")
center.grid(row=1, sticky="nsew")
footer.grid(row=2, sticky="ew")
# distributing equal weight (priority) to center frame columns
center.grid_columnconfigure(0, weight=1)
center.grid_columnconfigure(1, weight=1)
center.grid_columnconfigure(2, weight=1)
center.grid_rowconfigure(0, weight=1)
center.grid_rowconfigure(1, weight=1)
center.grid_rowconfigure(2, weight=1)
center.grid_rowconfigure(3, weight=1)
center.grid_rowconfigure(4, weight=1)
center.grid_rowconfigure(5, weight=1)
center.grid_rowconfigure(6, weight=1)
center.grid_rowconfigure(7, weight=1)
center.grid_rowconfigure(8, weight=1)
center.grid_rowconfigure(9, weight=1)
center.grid_rowconfigure(10, weight=1)
center.grid_rowconfigure(11, weight=1)
center.grid_rowconfigure(12, weight=1)
# label widget for the top frame
aibs_label = tk.Label(top_frame, text='Bid Generator', bg='#00c3ff').pack()
# Supported bank frames
bank_label = tk.Label(center, text='Supported Bank?', bg="gray", height=20).grid(row=0, columnspan=3, sticky="ew")
bank_left = tk.Frame(center, bg="red", padx=10, pady=10, height=10, width=10).grid(row=1, column=0, sticky="ew")
bank_mid = tk.Frame(center, bg="green", padx=10, pady=10, height=10, width=10).grid(row=1, column=1, sticky="ew")
bank_right = tk.Frame(center, bg="blue", padx=10, pady=10, height=10, width=10).grid(row=1, column=2, sticky="ew")
bank_yes = tk.Button(bank_left, text="Yes", width=24, height=3).grid()
bank_no = tk.Button(bank_mid, text="No", width=24, height=3).grid()
bank_name = tk.Button(bank_right, text="entry", width=24, height=3).grid()
# credit cards
cc_label = tk.Label(center, text='Credit cards?', bg="gray", height=20).grid(row=1, columnspan=3, sticky="ew")
cc_left = tk.Frame(center, bg="red", height=10, width=10).grid(row=2, column=0, sticky="ew")
cc_mid = tk.Frame(center, bg="green", height=10, width=10).grid(row=2, column=1, sticky="ew")
cc_right = tk.Frame(center, bg="blue", height=10, width=10).grid(row=2, column=2, sticky="ew")
# checks frames
chks_label = tk.Label(center, text='Checks?', bg="gray", height=20).grid(row=3, columnspan=3, sticky="ew")
chks_left = tk.Frame(center, bg="red", height=10, width=10).grid(row=4, column=0, sticky="ew")
chks_mid = tk.Frame(center, bg="green", height=10, width=10).grid(row=4, column=1, sticky="ew")
chks_right = tk.Frame(center, bg="blue", height=10, width=10).grid(row=4, column=2, sticky="ew")
# payroll frames
pr_label = tk.Label(center, text='Payroll?', bg="gray", height=20).grid(row=5, columnspan=3, sticky="ew")
pr_left = tk.Frame(center, bg="red", height=10, width=10).grid(row=6, column=0, sticky="ew")
pr_mid = tk.Frame(center, bg="green", height=10, width=10).grid(row=6, column=1, sticky="ew")
pr_right = tk.Frame(center, bg="blue", height=10, width=10).grid(row=6, column=2, sticky="ew")
# sales tax frames
st_label = tk.Label(center, text='Sales Tax?', bg="gray", height=20).grid(row=7, columnspan=3, sticky="ew")
st_left = tk.Frame(center, bg="red", height=10, width=10).grid(row=8, column=0, sticky="ew")
st_mid = tk.Frame(center, bg="green", height=10, width=10).grid(row=8, column=1, sticky="ew")
st_right = tk.Frame(center, bg="blue", height=10, width=10).grid(row=8, column=2, sticky="ew")
# workers comp frames
wc_label = tk.Label(center, text='Workers Comp?', bg="gray", height=20).grid(row=9, columnspan=3, sticky="ew")
wc_left = tk.Frame(center, bg="red", height=10, width=10).grid(row=10, column=0, sticky="ew")
wc_mid = tk.Frame(center, bg="green", height=10, width=10).grid(row=10, column=1, sticky="ew")
wc_right = tk.Frame(center, bg="blue", height=10, width=10).grid(row=10, column=2, sticky="ew")
# qbox frames
qbox_label = tk.Label(center, text='Qbox?', bg="gray", height=20).grid(row=11, columnspan=3, sticky="ew")
qbox_left = tk.Frame(center, bg="red", height=100, width=10).grid(row=12, column=0, sticky="ew")
qbox_mid = tk.Frame(center, bg="green", height=10, width=10).grid(row=12, column=1, sticky="ew")
qbox_right = tk.Frame(center, bg="blue", height=10, width=10).grid(row=12, column=2, sticky="ew")
# End of line
root.mainloop()
I have a program where the main window is divided into two sections each section has a collection of forms (simple label/input columns). The default is 4 of these columns in the first section and 2 in the second section. I would like the user to be able to change this ratio. I think I have all of the programming in place to do this, I just can't get the main window to redraw with the correct structure. Any help would be much appreciated. Thanks.
I like the simplicity and idea behind your example, however, I'm modifying some legacy code and don't have the time to rewrite my layouts as definitions. I tried to create a def that would simply do grid_columnconfig(), but that didn't work. I've reduced the code so that it looks like what I'm working with and it is also functional. If you change the variable 'max_pol_modules' it adjusts columns on the left versus columns on the right, so, I'm trying to change this variable through an interface widget and redraw.
from Tkinter import *
import tkFont
max_pol_modules = 3
max_bus_modules = 6 - max_pol_modules
tech_green = '#5E9732'
button_grey = '#666666'
grey = '#777777'
def config1():
global max_pol_modules, max_bus_modules
max_pol_modules = 1
max_bus_modules = 6 - max_pol_modules
# print max_bus_modules
# left_frame.update()
def config2():
global max_pol_modules, max_bus_modules
max_pol_modules = 2
max_bus_modules = 6 - max_pol_modules
# print max_bus_modules
def config3():
global max_pol_modules, max_bus_modules
max_pol_modules = 3
max_bus_modules = 6 - max_pol_modules
# print max_bus_modules
def config4():
global max_pol_modules, max_bus_modules
max_pol_modules = 4
max_bus_modules = 6 - max_pol_modules
# print max_bus_modules
def about():
box.showinfo("About GUI","GE Bus Converter and Point of Load GUI")
def bar(frame, row, span):
"create a bar to separate a section"
x = Frame(frame, relief=GROOVE, bd=2, width=86*(span+1), height=2)
x.grid(row=row, column=0, columnspan=10, pady=7, sticky=S+E)
x.grid_propagate(0)
def bar2(frame, row, span):
"create a bar to separate a section"
x = Frame(frame, relief=GROOVE, bd=2, width=86*(span+1), height=2)
x.grid(row=row, column=0, columnspan=10, pady=3, sticky=S+E)
x.grid_propagate(0)
def bar3(frame, row, span):
"create a bar to separate a section"
x = Frame(frame, relief=GROOVE, bd=2, width=100, height=2)
x.grid(row=row, column=0, columnspan=10, pady=7, sticky=S+E)
x.grid_propagate(0)
root = Tk()
menubar = Menu(root)
submenu=Menu(menubar,tearoff=0)
submenu2=Menu(submenu,tearoff=0)
submenu2.add_command(label="1 - 5", command=config1)
submenu2.add_command(label="2 - 4", command=config2)
submenu2.add_command(label="3 - 3", command=config3)
submenu2.add_command(label="4 - 2", command=config4)
submenu_help = Menu(submenu,tearoff=0)
submenu_help.add_command(label="About",command=about)
submenu.add_cascade(label="Change Configuration",menu=submenu2)
submenu.add_command(label="Exit", command=root.quit)
menubar.add_cascade(label="Settings",menu=submenu)
menubar.add_cascade(label="Help", menu=submenu_help)
# display the menu
root.config(menu=menubar)
entry_wid = 6
small_font = tkFont.Font(family='Arial', size=8, weight='bold')
lite_font = tkFont.Font(family='Arial', size=9)
large_font = tkFont.Font(family='Arial', size=9)
heading_font = tkFont.Font(family='Arial', size=10, weight='bold')
button_font = tkFont.Font(family='Arial', size=8, weight='bold')
root.option_add('*font', lite_font)
root.option_add('*background', '#C2C2C4')
root.option_add('*Label.font', small_font)
root.option_add('*Entry.background', 'white')
root.option_add('*Button.font', button_font)
root.option_add('*Button.background', button_grey)
root.option_add('*Button.foreground', 'yellow')
root.option_add('*Text.background', 'white')
root.option_add('*Text.font', small_font)
root.option_add('*ScrolledText.font', lite_font)
left_frame = Frame(root)
right_frame = Frame(root)
pol_frame = Frame(left_frame, bd=2, relief=SUNKEN)
x = Label(pol_frame, text="POL Address", anchor=E)
x.grid(row=0, column=0, sticky=E)
x = Label(pol_frame, text="Rtrim (Kohms)", anchor=E)
x.grid(row=1, column=0, sticky=E)
x = Label(pol_frame, text="Nominal Vout (V)", anchor=E)
x.grid(row=2, column=0, sticky=E)
bar2(pol_frame, 0, max_pol_modules)
module_address = []
module_i2c = []
module_status = []
module_resistor = []
module_vout_nominal = []
for i in range(max_pol_modules):
# Module ID and address
f = Frame(pol_frame)
x = Label(f, text=i+1)
x.grid(row=0, column=0)
v = StringVar()
x = Entry(f, textvariable=v, width=3, justify=CENTER)
x.grid(row=0, column=1)
f.grid(row=0, column=i+1, pady=8, padx=20)
module_address.append(v)
module_i2c.append("")
module_status.append(0)
# module resistor
v = StringVar()
x = Entry(pol_frame, textvariable=v, width=entry_wid, justify=CENTER)
f = lambda event, module=i: change_resistor_event(event, module)
g = lambda value, m=i, o=16: set_change(value, m, o)
x.bind("<KeyRelease>", f, "+")
x.bind("<KeyRelease>", g, "+")
x.bind("<FocusOut>", f, "+")
x.grid(row=1, column=i+1, pady=0)
module_resistor.append(v)
# module nominal vout
v = StringVar()
x = Label(pol_frame, textvariable=v, width=entry_wid-1,
relief=SUNKEN, bg='#DDDDDD', font=lite_font)
x.grid(row=2, column=i+1, pady=0)
module_vout_nominal.append(v)
bus_frame = Frame(left_frame, bd=2, relief=SUNKEN)
#x = Label(bus_frame, text="Module (address)", anchor=E)
#x.grid(row=0, column=max_pol_modules+1, sticky=E)
x = Label(bus_frame, text="Bus Conv Address", anchor=E)
x.grid(row=0, column=0, sticky=E)
config_bus = []
r = 0
#for i in range(max_pol_modules,max_pol_modules+max_bus_modules):
for i in range(max_bus_modules):
# Module ID and address
f = Frame(bus_frame)
x = Label(f, text=i+5)
x.grid(row=0, column=0)
v = StringVar()
x = Entry(f, textvariable=v, width=3, justify=CENTER)
x.grid(row=0, column=1)
f.grid(row=0, column=i+2, pady=8, padx=20)
module_address.append(v)
module_i2c.append("")
module_status.append(0)
bar2(bus_frame, r, max_bus_modules)
r += 1
# the measured values
measure_info = ["Vout (V)", "Iout (A)", "Vin (V)", "Temp (degC)"]
measures_bus = []
for mi in measure_info:
x = Label(bus_frame, text=mi, anchor=E)
x.grid(row=r, column=0, sticky=E)
m = []
for j in range(max_bus_modules):
v = StringVar()
x = Label(bus_frame, textvariable=v, width=entry_wid-1,
relief=SUNKEN, bg='#DDDDDD', font=lite_font)
x.grid(row=r, column=j+2)
m.append(v)
measures_bus.append(m)
r += 1
pol_frame.grid(row=0, column=0, sticky=N+W)
bus_frame.grid(row=0, column=1, sticky=N+W)
left_frame.grid(row=0, column=0, sticky=N)
right_frame.grid(row=0, column=1, sticky=N)
root.mainloop()
Edited Example where form[4] and form[5] need to be deleted.
import Tkinter as tk
class App(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.forms = []
self.toolbar = tk.Frame(self)
self.toolbar.pack(side="top", fill="x", expand=False)
button2 = tk.Button(self.toolbar, text="2 columns", command=self.layout2col)
button3 = tk.Button(self.toolbar, text="3 columns", command=self.layout3col)
button2.pack(side="left")
button3.pack(side="left")
self.forms_frame = tk.Frame(self, borderwidth=2, relief="groove")
self.forms_frame.pack(side="top", fill="both", expand="True", padx=2, pady=2)
for i in range(6):
frame = tk.LabelFrame(self.forms_frame, text="Form %s" % i)
self.forms.append(frame)
label = tk.Label(frame, text="Field %s" % i)
entry = tk.Entry(frame, width=20)
label.pack(side="left", fill="y")
entry.pack(side="left", fill="both", expand=True)
self.layout2col()
def layout3col(self):
self.forms[0].grid(column=0, row=0, padx=4, pady=2, sticky="ew")
self.forms[1].grid(column=0, row=1, padx=4, pady=2, sticky="ew")
self.forms[2].grid(column=1, row=0, padx=4, pady=2, sticky="ew")
self.forms[3].grid(column=1, row=1, padx=4, pady=2, sticky="ew")
self.forms[4].grid(column=2, row=0, padx=4, pady=2, sticky="ew")
self.forms[5].grid(column=2, row=1, padx=4, pady=2, sticky="ew")
self.forms_frame.grid_columnconfigure(0, weight=1)
self.forms_frame.grid_columnconfigure(1, weight=1)
self.forms_frame.grid_columnconfigure(2, weight=1)
def layout2col(self):
self.forms[0].grid(column=0, row=0, padx=4, pady=2, sticky="ew")
self.forms[1].grid(column=0, row=1, padx=4, pady=2, sticky="ew")
self.forms[2].grid(column=1, row=0, padx=4, pady=2, sticky="ew")
self.forms[3].grid(column=1, row=1, padx=4, pady=2, sticky="ew")
self.forms_frame.grid_columnconfigure(0, weight=1)
self.forms_frame.grid_columnconfigure(1, weight=1)
self.forms_frame.grid_columnconfigure(2, weight=0)
if __name__ == "__main__":
app = App()
app.mainloop()
Since you are using the grid geometry manager, you just need to use the grid method to place them in their new rows and columns. You may need to also call rowconfigure and/or columnconfigure to attach appropriate weights to the new rows and columns.
Here's a bit of a contrived example showing the general principle. It could be more efficient but hopefully it gives you a rough idea:
import Tkinter as tk
class App(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.forms = []
self.toolbar = tk.Frame(self)
self.toolbar.pack(side="top", fill="x", expand=False)
button2 = tk.Button(self.toolbar, text="2 columns", command=self.layout2col)
button3 = tk.Button(self.toolbar, text="3 columns", command=self.layout3col)
button2.pack(side="left")
button3.pack(side="left")
self.forms_frame = tk.Frame(self, borderwidth=2, relief="groove")
self.forms_frame.pack(side="top", fill="both", expand="True", padx=2, pady=2)
for i in range(6):
frame = tk.LabelFrame(self.forms_frame, text="Form %s" % i)
self.forms.append(frame)
label = tk.Label(frame, text="Field %s" % i)
entry = tk.Entry(frame, width=20)
label.pack(side="left", fill="y")
entry.pack(side="left", fill="both", expand=True)
self.layout2col()
def layout3col(self):
self.forms[0].grid(column=0, row=0, padx=4, pady=2, sticky="ew")
self.forms[1].grid(column=0, row=1, padx=4, pady=2, sticky="ew")
self.forms[2].grid(column=1, row=0, padx=4, pady=2, sticky="ew")
self.forms[3].grid(column=1, row=1, padx=4, pady=2, sticky="ew")
self.forms[4].grid(column=2, row=0, padx=4, pady=2, sticky="ew")
self.forms[5].grid(column=2, row=1, padx=4, pady=2, sticky="ew")
self.forms_frame.grid_columnconfigure(0, weight=1)
self.forms_frame.grid_columnconfigure(1, weight=1)
self.forms_frame.grid_columnconfigure(2, weight=1)
def layout2col(self):
self.forms[0].grid(column=0, row=0, padx=4, pady=2, sticky="ew")
self.forms[1].grid(column=0, row=1, padx=4, pady=2, sticky="ew")
self.forms[2].grid(column=0, row=2, padx=4, pady=2, sticky="ew")
self.forms[3].grid(column=1, row=0, padx=4, pady=2, sticky="ew")
self.forms[4].grid(column=1, row=1, padx=4, pady=2, sticky="ew")
self.forms[5].grid(column=1, row=2, padx=4, pady=2, sticky="ew")
self.forms_frame.grid_columnconfigure(0, weight=1)
self.forms_frame.grid_columnconfigure(1, weight=1)
self.forms_frame.grid_columnconfigure(2, weight=0)
if __name__ == "__main__":
app = App()
app.mainloop()
You've probably already tried this, but can you call update() on your root widget?
You might also need to pack() again, first.