set the correct Tkinter widgets position in Python - python

i am writing a GUI for a RAW image converter in Python using Tkinter. The GUI is divide in three part. The part A has a button to import the RAW file, the part B has four Checkbuttons, and the part C has Checkbuttons with two Entry spaces.
The length of the columns 0 (= the first) is given by the label "correct chromatic aberration" (the longest element). This mean if i change the name for example in correct chromatic aberration for white balance" all elements are shifted as the image below, and the part A, B, and C are related each other.
I wish to make independent the part A to the part B, and so on, in order to have the below image. In other words i wish to place each block of buttons into their own frame, and the frames in the main window.
the original code is:
from __future__ import division
from Tkinter import *
import tkMessageBox
import tkFileDialog
class MainWindow(Frame):
def __init__(self):
Frame.__init__(self)
self.master.title("FOO converter")
self.master.minsize(350, 150)
self.grid(sticky=E+W+N+S)
self.save_dir = None
self.filename_open = None
top = self.winfo_toplevel()
top.rowconfigure(0, weight=1)
top.columnconfigure(0, weight=1)
self.CHART_FILE_TYPES = [('Pentax Electronic Format', '*.pef'),
('Sony Alpha Raw', '*.arw'),
('Minolta Raw', '*.mrw'),
('Camera Image File Format', '*.crw'),
('Canon Raw', '*.cr2'),
('Epson Raw', '*.erw'),
('Samsung Raw', '*.srw'),
('Fujifilm Raw', '*.raf'),
('Kodak Digital Camera Raw', '*.dcr'),
('Nikon Electronic Format', '*.nef'),
('Olympus Raw', '*.orf'),
('All files', '.*')]
for i in range(10): self.rowconfigure(i, weight=1)
self.columnconfigure(1, weight=1)
self.open = Button(self, text='Input raw image file', command=self.open, activeforeground="red")
self.open.grid(row=0, column=0, pady=2, padx=2, sticky=E+W+N+S)
self.sep = Frame(self, height=2, width=450, bd=1, relief=SUNKEN)
self.sep.grid(row=1, column=0, columnspan=4, padx=5, pady=5)
self.CheckVar_camera_white_balance = IntVar()
self.CheckVar_camera_white_balance = Checkbutton(self,
text="Camera white balance",
variable=self.CheckVar_camera_white_balance,
onvalue=1,
offvalue=0)
self.CheckVar_camera_white_balance.grid(row=2, column=0, pady=0, padx=0, sticky=W)
self.CheckVar_average_whole_image_white_balance = IntVar()
self.CheckVar_average_whole_image_white_balance = Checkbutton(self,
text="Average the whole image for white balance",
variable=self.CheckVar_average_whole_image_white_balance,
onvalue=1,
offvalue=0)
self.CheckVar_average_whole_image_white_balance.grid(row=3, column=0, pady=0, padx=0, sticky=W)
self.CheckVar_correct_chromatic_aberration = IntVar()
self.CheckVar_correct_chromatic_aberration = Checkbutton(self,
text="Correct chromatic aberration",
variable=self.CheckVar_correct_chromatic_aberration,
onvalue=1,
offvalue=0)
self.CheckVar_correct_chromatic_aberration.grid(row=4, column=0, pady=0, padx=0, sticky=W)
self.CheckVar_fix_dead_pixels = IntVar()
self.CheckVar_fix_dead_pixels = Checkbutton(self,
text="Fix dead pixels",
variable=self.CheckVar_fix_dead_pixels,
onvalue=1,
offvalue=0)
self.CheckVar_fix_dead_pixels.grid(row=5, column=0, pady=0, padx=0, sticky=W)
self.sep = Frame(self, height=2, width=450, bd=1, relief=SUNKEN)
self.sep.grid(row=6, column=0, columnspan=4, padx=5, pady=5)
self.CheckVar_brightness = IntVar()
self.CheckVar_brightness = Checkbutton(self, text="Brightness",
command=self.switch_brightness,
variable=self.CheckVar_brightness,
onvalue=1,
offvalue=0)
self.CheckVar_brightness.grid(row=7, column=0, pady=0, padx=2, sticky=W)
self.label_level_brightness = Label(self, text="Brightness level:", state=DISABLED)
self.label_level_brightness.grid(row=8, column=0, pady=0, padx=0, sticky=W)
self.entry_level_brightness = Entry(self, state=DISABLED)
self.entry_level_brightness.grid(row=8, column=1, pady=0, padx=0, sticky=W)
self.label_gamma_curve = Label(self, text="Gamma curve:", state=DISABLED)
self.label_gamma_curve.grid(row=9, column=0, pady=0, padx=0, sticky=W)
self.entry_gamma_curve_1 = Entry(self, state=DISABLED)
self.entry_gamma_curve_1.grid(row=9, column=1, pady=0, padx=0, sticky=W)
self.entry_gamma_curve_2 = Entry(self, state=DISABLED)
self.entry_gamma_curve_2.grid(row=9, column=2, pady=0, padx=0, sticky=E+W+N+S)
# functions
def open(self):
self.filename_open = tkFileDialog.askopenfilename(filetypes=self.CHART_FILE_TYPES, defaultextension='.*')
def switch_brightness(self):
pass
if __name__ == "__main__":
d = MainWindow()
d.mainloop()

If you want the regions to be independent, use a frame for each region. For example:
top_frame = Frame(self, ...)
middle_frame = Frame(self, ...)
bottom_frame = Frame(self, ...)
top_frame.pack(side="top", fill="x")
middle_frame.pack(side="top", fill="x")
bottom_frame.pack(side="top", fill="x")
With that, you can now treat each region independently. This now affords you the luxury of using different geometry managers for different sections. You may want to use pack in the top and middle frame, and grid in the lower frame.
# Top frame
self.open = Button(top_frame, ...)
self.open.pack(side="left")
...
# Middle frame
self.CheckVar_camera_white_balance = Checkbutton(middle_frame, ...)
self.CheckVar_camera_white_balance.pack(side="top", fill="x")
...
# Bottom frame
self.CheckVar_brightness = Checkbutton(bottom_frame, ...)
self.CheckVar_brightness.grid(row=0, column=0, pady=0, padx=2, sticky=W)
...

Related

tkinter resize GUI on different monitors

I am mainly coding on my MAC.
I created a GUI that is used for a tool I am using to automate things with selenium.
I have used .grid for all widgets in my GUI.
But when I open the GUI on my Windows laptop at home (same resolution but much smaller monitor panel) it is totally messed up.
Here are two screenshot showing the problem,
Messed up layout on Win Laptop (17,3")
The second screenshot shows how it should look.
This is the code I used for the grid layout:
# General GUI settings
app = Tk()
app.title('trade_buddy')
app.geometry('605x800')
app.minsize(605, 800)
app.maxsize(605, 800)
app.grid_rowconfigure(0, weight=1)
app.grid_rowconfigure(1, weight=1)
app.grid_rowconfigure(2, weight=1)
app.grid_rowconfigure(3, weight=1)
app.grid_rowconfigure(4, weight=1)
app.grid_rowconfigure(5, weight=1)
app.grid_rowconfigure(6, weight=1)
app.grid_rowconfigure(7, weight=1)
app.grid_rowconfigure(8, weight=1)
app.grid_rowconfigure(9, weight=1)
app.grid_rowconfigure(10, weight=1)
app.grid_rowconfigure(11, weight=1)
app.grid_rowconfigure(12, weight=1)
app.grid_rowconfigure(13, weight=1)
#Background label
image = Image.open('v2.0/lolo.png')
image = image.resize((600,450), Image.ANTIALIAS)
copy_of_image = image.copy()
photo = ImageTk.PhotoImage(image)
label = tk.Label(app, image = photo)
label.place(x=0, y=0)
#Buttons
b_init = tk.Button(app,text='Initialize',font='Tahoma 10 bold',bg='#f8f09d',fg='#1e1e1f',activebackground='#1e1e1f',activeforeground='#f8f09d',padx=8, pady=10, command=lambda:threading.Thread(target=tb,daemon=True).start())
b_exit = tk.Button(app,text='Exit',font='Tahoma 10 bold',padx=8,bg='#f8f09d',fg='#1e1e1f',activebackground='#1e1e1f',activeforeground='#f8f09d', pady=10,command=lambda:threading.Thread(target=exit_tb,daemon=True).start())
b_start = tk.Button(app,text='Start',font='Tahoma 10 bold',bg='#f8f09d',fg='#1e1e1f',activebackground='#1e1e1f',activeforeground='#f8f09d',padx=8, pady=10,command=lambda:threading.Thread(target=filters,daemon=True).start())
b_pause = tk.Button(app,text='Pause',font='Tahoma 10 bold',bg='#f8f09d',fg='#1e1e1f',activebackground='#1e1e1f',activeforeground='#f8f09d',padx=8, pady=10,command=lambda:threading.Thread(target=stop_tb,daemon=True).start())
b_tfm = tk.Button(app,text='TFM',font='Tahoma 10 bold',bg='#f8f09d',fg='#1e1e1f',activebackground='#1e1e1f',activeforeground='#f8f09d',padx=8, pady=10,command=lambda:threading.Thread(target=tfm,daemon=True).start())
#Labels
l_maxBO = tk.Label(app,text='Maximum buy price:',bg='#1e1e1f', fg='#f8f09d',font='Tahoma 10')
l_itemsontf = tk.Label(text='# of items on transfer list:',bg='#1e1e1f', fg='#f8f09d',font='Tahoma 10')
l_speed = tk.Label(text='Choose speed:',bg='#1e1e1f', fg='#f8f09d',font='Tahoma 10 bold')
l_routine = tk.Label(text='Choose routine:',bg='#1e1e1f', fg='#f8f09d',font='Tahoma 10 bold')
#Entries
e_maxBO = tk.Entry(app, width=10, bg='#1e1e1f', fg='#f8f09d', font='Tahoma 10')
e_itemsontf = tk.Entry(app, width=10, bg='#1e1e1f', fg='#f8f09d',font='Tahoma 10')
e_fixedsellprice = tk.Entry(app, width=10, bg='#1e1e1f', fg='#f8f09d',font='Tahoma 10')
#Text box
t_outputbox = tk.Text(app, width=99, height=27, font='Tahoma 10',bg='#2c2c2c', fg='#f8f09d', relief=SUNKEN, highlightthickness="1")
#Grid Layout
l_maxBO.grid(row=0, column=0, sticky='w', padx=5, pady=5)
l_itemsontf.grid(row=1, column=0, sticky='w', padx=5, pady=5)
l_speed.grid(row=3, column=0, sticky='w', padx=5, pady=1, ipady=1)
l_routine.grid(row=7, column=0, sticky='w', padx=5, pady=1, ipady=1)
e_maxBO.grid(row=0, column=1, sticky='w', padx=5, pady=5)
e_itemsontf.grid(row=1, column=1, sticky='w', padx=5, pady=5)
e_fixedsellprice.grid(row=11, column=0, sticky='w', padx=5, pady=3)
b_exit.grid(row=12, column=8, sticky='sw', padx=5, pady=10)
b_init.grid(row=12, column=4, sticky='sw', padx=5, pady=10)
b_start.grid(row=12, column=0, sticky='sw', padx=5, pady=10)
b_pause.grid(row=12, column=1, sticky='sw', padx=5, pady=10)
b_tfm.grid(row=12, column=2, sticky='sw', padx=5, pady=10)
r_normal.grid(row=4, column=0, sticky='w', padx=5, pady=1)
r_fast.grid(row=5, column=0, sticky='w', padx=5, pady=1)
r_slow.grid(row=6, column=0, sticky='w', padx=5, pady=1)
r_buyonly.grid(row=8, column=0, sticky='w', padx=5, pady=1)
r_fullroutine.grid(row=9, column=0, sticky='w', padx=5, pady=1)
r_buysellfixed.grid(row=10, column=0, sticky='w', padx=5, pady=1)
t_outputbox.grid(row=13, column=0, columnspan=13, rowspan=13, sticky='nsew', padx=5, pady=10)
As a coding beginner, I really have no idea what else I could change.
I already changed from .place to .grid but the problem is still the same.
Does anyone have an idea how I could setup my GUI that it keeps the minimum required geometry relations no matter on what monitor I work?
Here is an example of forcing it to look like the second picture.
import tkinter as tk
from PIL import ImageTk, Image
# General GUI settings
app = tk.Tk()
app.configure(bg="black")
#Background label
image = Image.open('test.png')
image = image.resize((200,200), Image.ANTIALIAS)
copy_of_image = image.copy()
photo = ImageTk.PhotoImage(image)
label = tk.Label(app, image = photo)
label.grid(row=3, column=1, sticky='w')
#others
r_normal = tk.Radiobutton(app, text="Normal Speed")
r_fast = tk.Radiobutton(app, text="Fast Speed")
r_slow = tk.Radiobutton(app, text="Slow Speed")
r_buyonly = tk.Radiobutton(app, text="Buy only")
r_fullroutine = tk.Radiobutton(app, text="Full routine (optimized price)")
r_buysellfixed = tk.Radiobutton(app, text="Buy and sell for fixed price")
#Buttons
b_init = tk.Button(app,text='Initialize',font='Tahoma 10 bold',bg='#f8f09d',fg='#1e1e1f',activebackground='#1e1e1f',activeforeground='#f8f09d',padx=8, pady=10, command=lambda:threading.Thread(target=tb,daemon=True).start())
b_exit = tk.Button(app,text='Exit',font='Tahoma 10 bold',padx=8,bg='#f8f09d',fg='#1e1e1f',activebackground='#1e1e1f',activeforeground='#f8f09d', pady=10,command=lambda:threading.Thread(target=exit_tb,daemon=True).start())
b_start = tk.Button(app,text='Start',font='Tahoma 10 bold',bg='#f8f09d',fg='#1e1e1f',activebackground='#1e1e1f',activeforeground='#f8f09d',padx=8, pady=10,command=lambda:threading.Thread(target=filters,daemon=True).start())
b_pause = tk.Button(app,text='Pause',font='Tahoma 10 bold',bg='#f8f09d',fg='#1e1e1f',activebackground='#1e1e1f',activeforeground='#f8f09d',padx=8, pady=10,command=lambda:threading.Thread(target=stop_tb,daemon=True).start())
b_tfm = tk.Button(app,text='TFM',font='Tahoma 10 bold',bg='#f8f09d',fg='#1e1e1f',activebackground='#1e1e1f',activeforeground='#f8f09d',padx=8, pady=10,command=lambda:threading.Thread(target=tfm,daemon=True).start())
#Labels
l_maxBO = tk.Label(app,text='Maximum buy price:',bg='#1e1e1f', fg='#f8f09d',font='Tahoma 10')
l_itemsontf = tk.Label(text='# of items on transfer list:',bg='#1e1e1f', fg='#f8f09d',font='Tahoma 10')
l_speed = tk.Label(text='Choose speed:',bg='#1e1e1f', fg='#f8f09d',font='Tahoma 10 bold')
l_routine = tk.Label(text='Choose routine:',bg='#1e1e1f', fg='#f8f09d',font='Tahoma 10 bold')
#Entries
e_maxBO = tk.Entry(app, width=10, bg='#1e1e1f', fg='#f8f09d', font='Tahoma 10')
e_itemsontf = tk.Entry(app, width=10, bg='#1e1e1f', fg='#f8f09d',font='Tahoma 10')
e_fixedsellprice = tk.Entry(app, width=10, bg='#1e1e1f', fg='#f8f09d',font='Tahoma 10')
#Text box
t_outputbox = tk.Text(app, width=99, height=27, font='Tahoma 10',bg='#2c2c2c', fg='#f8f09d', relief=tk.SUNKEN, highlightthickness="1")
#Grid Layout
l_maxBO.grid(row=0, column=0, sticky='w', padx=5, pady=5)
l_itemsontf.grid(row=1, column=0, sticky='w', padx=5, pady=5)
l_speed.grid(row=3, column=0, sticky='w', padx=5, pady=1, ipady=1)
l_routine.grid(row=7, column=0, sticky='w', padx=5, pady=1, ipady=1)
e_maxBO.grid(row=0, column=1, sticky='w', padx=5, pady=5)
e_itemsontf.grid(row=1, column=1, sticky='w', padx=5, pady=5)
e_fixedsellprice.grid(row=11, column=0, sticky='w', padx=5, pady=3)
b_exit.grid(row=12, column=8, sticky='sw', padx=5, pady=10)
b_init.grid(row=12, column=4, sticky='sw', padx=5, pady=10)
b_start.grid(row=12, column=0, sticky='sw', padx=5, pady=10)
b_pause.grid(row=12, column=1, sticky='sw', padx=5, pady=10)
b_tfm.grid(row=12, column=2, sticky='sw', padx=5, pady=10)
r_normal.grid(row=4, column=0, sticky='w', padx=5, pady=1)
r_fast.grid(row=5, column=0, sticky='w', padx=5, pady=1)
r_slow.grid(row=6, column=0, sticky='w', padx=5, pady=1)
r_buyonly.grid(row=8, column=0, sticky='w', padx=5, pady=1)
r_fullroutine.grid(row=9, column=0, sticky='w', padx=5, pady=1)
r_buysellfixed.grid(row=10, column=0, sticky='w', padx=5, pady=1)
t_outputbox.grid(row=13, column=0, columnspan=13, rowspan=13, sticky='nsew', padx=5, pady=10)
Notable differences:
I had to set a background color to make up for how we are moving that image.
The image is no longer using .place and instead using .grid.
The image will need to be resized a bit differently because it is a smaller area.
I removed all those row_configures because they were removing some rigidity, you can add it back if you like, but you'll have to re-scale your columns to match the new layout.
Let us know if you have any questions etc.

Tkinter anchor left on gridbox

I have packaged a group a widgets into a single widget as follows:
class RunOptions(tk.Frame):
def __init__(self, master=None):
super().__init__(master, bg='green')
self.label = tk.Label(self, text='Options:')
self.folder_button_label = tk.Label(self, text='Select a Folder', bg='white')
self.folder_button = tk.Button(self, text='Select Image Folder')
self.template_button = tk.Button(self, text='Select Template')
self.template_frame = ImageCanvas(self, height=64, width=64)
self.label.grid(row=0, sticky='W')
self.folder_button.grid(row=1, column=1, sticky='W')
self.folder_button_label.grid(row=1, column=0, sticky='W')
self.template_button.grid(row=2, column=1, sticky='W')
self.template_frame.grid(row=2, column=0, sticky='W')
and
class DetectionCanvas(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.xml_var = tk.IntVar()
self.detectframe = ImageCanvas(self, label='Detection:', height=175, width=175)
self.x_out = tk.Label(self, bg='white', text='X:', anchor='w')
self.y_out = tk.Label(self, bg='white', text='Y:', anchor='w')
self.w_out = tk.Label(self, bg='white', text='W:', anchor='w')
self.h_out = tk.Label(self, bg='white', text='H:', anchor='w')
self.xml_check = tk.Checkbutton(self, text=' Save XML File',variable=self.xml_var)
self.detectframe.grid(row=0, column=0, rowspan=4)
self.x_out.grid(row=0, column=1)
self.y_out.grid(row=1, column=1)
self.w_out.grid(row=2, column=1)
self.h_out.grid(row=3, column=1)
self.xml_check.grid(row=4, column=0, sticky='w')
def display_out(self, *args):
pass
both of these widgets are all arranged in a large empty canvas (purple) using grid, but that doesn't matter here because the issue is in the individual widgets themselves:
I want the buttons in the options to anchor to the left, filling in the gap between the label. For the detection widget I want the labels to anchor left towards the canvas. I've tried anchoring and using sticky but nothing in the second column seems to move.

Dynamically fit tkinter window to its content

I have a Toplevel Window with one grid row containing a Label, Entry and a "+" Button (window on startup)
When I hit the Add-Button a new row with the same content is generated. But the problem is, that the window doesn't resize and fit to its new contents. Should look like this resized window.
The code is below:
def process_map():
numbers = {0:'\u2080', 1:'\u2081', 2:'\u2082', 3:'\u2083', 4:'\u2084', 5:'\u2085', 6:'\u2086', 7:'\u2087', 8:'\u2088', 9:'\u2089'}
button_pos = tk.IntVar(0)
ENTRIES = {}
def add_button():
if button_pos.get() >= 10:
index = numbers[button_pos.get()//10] + numbers[button_pos.get()%10]
else:
index = numbers[button_pos.get()]
lb = tk.Label(top_root, text='\u03C6'+index)
lb.grid(row=button_pos.get(), column=0, sticky='NWES')
entry = tk.Entry(top_root, width=4, relief='sunken', bd=2)
entry.grid(row=button_pos.get(), column=1, sticky='WE', padx=5, pady=5)
ENTRIES.update({button_pos.get():entry})
bt.grid(row=button_pos.get(), column=2, sticky='WE', padx=5, pady=5)
bt_close.grid(row=button_pos.get()+1, column=1, padx=5, pady=5)
bt_start.grid(row=button_pos.get()+1, column=0, padx=5, pady=5)
button_pos.set(button_pos.get()+1)
center(top_root)
top_root = tk.Toplevel(root)
top_root.title('Select \u03C6')
lb = tk.Label(top_root, text='\u03C6\u2081', height=1)
lb.grid(row=0, column=0, sticky='NWES')
entry = tk.Entry(top_root, width=4, relief='sunken', bd=2)
entry.grid(row=0, column=1, sticky='WE', padx=5, pady=5)
button_pos.set(button_pos.get()+2)
ENTRIES.update({button_pos.get():entry})
bt = tk.Button(top_root, text='+', command=add_button,)
bt.grid(row=0, column=2, sticky='WE', padx=5, pady=5)
bt_close = tk.Button(top_root, text='Cancel', width=15, command=top_root.destroy)
bt_close.grid(row=button_pos.get()+1, column=1, padx=5, pady=5)
bt_start = tk.Button(top_root, text='Start', width=15)
bt_start.grid(row=button_pos.get()+1, column=0, padx=5, pady=5)
center(top_root)
top_root.mainloop()

Radiobutton modifying increment values in spinbox Python

I'm trying to create a GUI in Python 2.7 with Tkinter. I need that the increment value from my Spinbox changes accordingly to a value selected from a selection of Radiobutton. I've tried different approaches but not success so far. I'm attaching part of the code that isn't working. I really appreciate if someone could come up with a solution. Thanks!
class Frequency_Window(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def initUI(self):
global var_increment
self.var_x = IntVar()
self.self_value = IntVar()
self.freq_Hz = IntVar()
self.parent.title("Test")
self.pack(fill=BOTH, expand=1)
self.columnconfigure(1, weight=1)
self.columnconfigure(1, pad=7)
self.rowconfigure(5, weight=1)
self.rowconfigure(5, pad=7)
self.var_x.set("1")
label_RadioButton = ttk.Label(self,
justify=LEFT,
text="Increments")
label_RadioButton.grid(sticky=N+W+S+E,
pady=4,
padx=5,
row=0,
column=1)
R1 = ttk.Radiobutton(self,
text="1",
variable=self.var_x,
command=self.set_increment,
value=1)
R1.grid(sticky=NW,
row=1,
column=1,
pady=5)
R10 = ttk.Radiobutton(self,
text="10",
variable=self.var_x,
command=self.set_increment,
value=10)
R10.grid(sticky=NW,
row=2,
column=1,
pady=5)
R100 = ttk.Radiobutton(self,
text="100",
variable=self.var_x,
command=self.set_increment,
value=100)
R100.grid(sticky=NW,
row=3,
column=1,
pady=5)
var_freq_Hz = Spinbox(self,
textvariable=self.freq_Hz,
font=("Calibri",30),
justify="right",
bd=0,
bg='black',
fg='white',
from_=0,
to=999,
increment=self.var_x.get(),
width=4,
relief=FLAT,
buttonbackground='black')
var_freq_Hz.grid(sticky=N+W+S+E,
row=1,
column=0,
columnspan=1,
rowspan=1,
padx=5)
def set_increment(self):
selection = "You selected the option " + str(self.var_x.get())
print selection
return
Hi I just found the way to do it. I had to change my object available in the class adding it to self. From this:
var_freq_Hz = Spinbox(self,
textvariable=self.freq_Hz,
font=("Calibri",30),
justify="right",
bd=0,
bg='black',
fg='white',
from_=0,
to=999,
increment=self.var_x.get(),
width=4,
relief=FLAT,
buttonbackground='black')
var_freq_Hz.grid(sticky=N+W+S+E,
row=1,
column=0,
columnspan=1,
rowspan=1,
padx=5)
To this:
self.var_freq_Hz = Spinbox(self,
textvariable=self.freq_Hz,
font=("Calibri",30),
justify="right",
bd=0,
bg='black',
fg='white',
from_=0,
to=999,
width=4,
relief=FLAT,
buttonbackground='black')
self.var_freq_Hz.grid(sticky=N+W+S+E,
row=1,
column=0,
columnspan=1,
rowspan=1,
padx=5)
And then in the call function, I used the configure option to change the value of increment, as this:
def set_increment(self):
selection = "You selected the option " + str(self.var_x.get())
self.var_freq_Hz.config(increment = self.var_x.get())
print selection
return
Now it's working properly. However, if someone comes up with a more Pythonic solution is highly appreciate! Cheers!

Using Python and TKinter, how do I redraw the main screen

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.

Categories

Resources