Tkinter scale widget labeling - python

I am new to Tkinter and try to make a little password generator. For the length of the password I want to implement a Scale widget. I have a weird problem with displaying the labeling of the widget, I do not understand why I get two different designs.
So this is a snippet from my main program:
root = Tk()
root.geometry("460x100")
root.resizable(0,0)
root.title("Password Generator")
pw_label = Label(root, text="Password").grid(row=0, column=0, pady=4, padx = 4)
length_label = Label(root, text="Length").grid(row=2, column=0, pady=4, padx = 4)
pw_input = Entry(root, width=50)
length_input = Scale(root, from_=8, to=50, orient=HORIZONTAL, length= 300)
length_input.set(30)
pw_input.grid(row = 0, column = 1, pady=4, padx = 4)
length_input.grid(row = 2, column = 1, pady=4, padx = 4)
Button(root, text='Quit', command=root.quit).grid(row=3, column=2, sticky=W, pady=4)
Button(root, text='Generate', command=rand_pw).grid(row=2, column=2, sticky=W, pady=4)
Button(root, text='Copy', command=copy).grid(row=0, column=2, sticky=W, pady=4)
root.mainloop()
As you can see, I have a blue slider and I have no scale under the Scale.
And here is another, minimal slider example:
from tkinter import *
root = Tk()
root.geometry("500x100")
length_label = Label(root, text="Length").grid(row=0, column=0, pady=4, padx = 4)
w2 = Scale(root, from_=0, to=50, tickinterval= 50, orient=HORIZONTAL, length=400)
w2.set(23)
w2.grid(row=0, column=1)
mainloop()
Can someone explain to me why I get two different stylings there? Both programs are in the same project folder in PyCharm. Also I start both examples in the same environment.
I think I just made a stupid mistake but I can not find it.

Refering to #Bryan Oakley´s answer I removed the from tkinter.ttk import * and afterwards I got the design as shown in my second screenshot.
Just deleted this one line although here is the working snippet.
from tkinter.ttk import *
root = Tk()
root.geometry("460x100")
root.resizable(0,0)
root.title("Password Generator")
pw_label = Label(root, text="Password").grid(row=0, column=0, pady=4, padx = 4)
length_label = Label(root, text="Length").grid(row=2, column=0, pady=4, padx = 4)
pw_input = Entry(root, width=50)
length_input = Scale(root, from_=8, to=50, orient=HORIZONTAL, length= 300)
length_input.set(30)
pw_input.grid(row = 0, column = 1, pady=4, padx = 4)
length_input.grid(row = 2, column = 1, pady=4, padx = 4)
Button(root, text='Quit', command=root.quit).grid(row=3, column=2, sticky=W, pady=4)
Button(root, text='Generate', command=rand_pw).grid(row=2, column=2, sticky=W, pady=4)
Button(root, text='Copy', command=copy).grid(row=0, column=2, sticky=W, pady=4)
root.mainloop()

Related

Problem with positioning widgets right next to each other with tkinter

So, I have this piece of code:
import tkinter as tk
root = tk.Tk()
root.geometry("400x300")
root.columnconfigure(0, weight=1, minsize=75)
root.rowconfigure(0, weight=1, minsize=50)
subjects = ["None"]
frm_new_grade = tk.Frame()
lbl_new_grade = tk.Label(text="New Grade", font="System")
lbl_add_subject = tk.Label(frm_new_grade, text="Subject:", font="System")
lbl_add_subject.grid(row=0, column=0, sticky="E")
subject_value = tk.StringVar(frm_new_grade)
subject_value.set("Select an Option")
question_menu = tk.OptionMenu(frm_new_grade, subject_value, *subjects)
question_menu_menu = root.nametowidget(question_menu.menuname)
question_menu_menu.config(font="System")
question_menu.config(font="System")
question_menu.grid(row=0, column=1, sticky="W")
btn_new_subject = tk.Button(frm_new_grade, text="+", font="System", width=2)
btn_new_subject.grid(row=0, column=2, padx=5, sticky="W")
lbl_add_grade = tk.Label(frm_new_grade, text="Grade:", font="System")
lbl_add_grade.grid(row=1, column=0, sticky="E")
ent_add_grade = tk.Entry(frm_new_grade, font="System", width=18)
ent_add_grade.grid(row=1, column=1, columnspan=2, sticky="W")
btn_add_grade = tk.Button(frm_new_grade, text="Add Grade", font="System")
btn_add_grade.grid(row=2, column=1, sticky="W", pady=5)
frm_new_grade.grid()
root.mainloop()
My problem is that I want btn_new_subject to be right next to question_menu at all times, like when question_menu has "Select an Option", but not like when I select "None"
I tried to fix this using columnspan on ent_add_grade (like you see on my code), I thought that this with the sticky properties of btn_new_subject would make it so that they are right next to each other, but instead I get btn_new_subject placed like if it had no sticky property.
I'm quite new to programming and python so any feedback will be appreciated.
You can just set sticky="EW" in question_menu.grid(...) so that question_menu will fill the space horizontally in the cell.
Result:
There is typo error missing for lbl_new_grade.grid()
In line 12, add root for lbl_new_grade(frm_new_grade,
Set all row=x, column=0. The x denote 1, 2 and 3. While row=2
column=1. And for btn_add_grade.grid(row=3, column=1
If you like layout for root.geometry("235x150")
If you like w/out glitch for layout. Then set index to 1
root.columnconfigure(1,
It is up to you to decide.
Snippet for readability:
import tkinter as tk
root = tk.Tk()
root.geometry("235x150")
root.columnconfigure(0, weight=1, minsize=75)
root.rowconfigure(3, weight=1, minsize=50)
subjects = ["None"]
frm_new_grade = tk.Frame()
lbl_new_grade = tk.Label(frm_new_grade, text="New Grade", bg='red', font="System")
lbl_new_grade.grid(row=0, column=1)
lbl_add_subject = tk.Label(frm_new_grade, text="Subject:", font="System")
lbl_add_subject.grid(row=1, column=0, sticky="WE", pady=10)
subject_value = tk.StringVar(frm_new_grade)
subject_value.set("Select an Option")
question_menu = tk.OptionMenu(frm_new_grade, subject_value, *subjects)
question_menu_menu = root.nametowidget(question_menu.menuname)
question_menu_menu.config(font="System")
question_menu.config(font="System")
question_menu.grid(row=1, column=1, sticky="WE")
btn_new_subject = tk.Button(frm_new_grade, text="+", font="System", width=2)
btn_new_subject.grid(row=1, column=2, padx=5, sticky="WE")
lbl_add_grade = tk.Label(frm_new_grade, text="Grade:", font="System")
lbl_add_grade.grid(row=2, column=0, sticky="W")
ent_add_grade = tk.Entry(frm_new_grade, font="System", width=18)
ent_add_grade.grid(row=2, column=1, columnspan=2, sticky="W")
btn_add_grade = tk.Button(frm_new_grade, text="Add Grade", font="System")
btn_add_grade.grid(row=3, column=1, sticky="W", pady=5)
frm_new_grade.grid()
root.mainloop()
Screenshot:

incorrect button width using grid in tkinter

Somehow the buttons placed using grid method will be much bigger than the cell width defined by columnconfigure. I tried to place some test labels in the same way, and it worked as expected. Is there any way to get correct button width like these labels did?
Below is the simplified code to the question:
import tkinter as tk
from tkinter.ttk import *
root = tk.Tk()
style = Style()
style.theme_use('clam')
style.configure('TestLabel1.TLabel', background='red')
style.configure('TestLabel2.TLabel', background='green')
style.configure('TestLabel3.TLabel', background='blue')
style.configure('Buttons.TButton')
output_path = tk.StringVar()
output_path.set('test')
settings = Frame(root, width=500, height=200)
settings.pack_propagate(0)
settings.pack(side='top')
chart_preset_frame = LabelFrame(settings, text='Chart Parameter Preset', padding=(5, 5, 5, 5))
chart_preset_frame.pack(expand=True, fill='x', pady=10, side='top')
chart_preset_frame.columnconfigure(0, weight=6)
chart_preset_frame.columnconfigure(1, weight=2)
chart_preset_frame.columnconfigure(2, weight=2)
output_path_input = Entry(chart_preset_frame, textvariable=output_path, width=20)
output_path_input.grid(row=0, column=0, columnspan=3, sticky='EW', ipady=5)
output_load_btn = Button(chart_preset_frame, text='Load...', style='Buttons.TButton', command=None)
output_load_btn.grid(row=1, column=1, sticky='EW', padx=0, pady=5)
output_save_btn = Button(chart_preset_frame, text='Save As...', style='Buttons.TButton', command=None)
output_save_btn.grid(row=1, column=2, sticky='EW', padx=0, pady=5)
# for label test
# label_test_1 = Label(chart_preset_frame, text='test', style='TestLabel1.TLabel')
# label_test_1.grid(row=1, column=0, sticky='EW')
# label_test_2 = Label(chart_preset_frame, text='test', style='TestLabel2.TLabel')
# label_test_2.grid(row=1, column=1, sticky='EW')
# label_test_3 = Label(chart_preset_frame, text='test', style='TestLabel3.TLabel')
# label_test_3.grid(row=1, column=2, sticky='EW')
root.mainloop()
weight is just a guideline to the layout manager how to distribute available spaces. Since there is no widget in cell (row 1, column 0), it may not get the required space.
It can be enforced by adding uniform=1 to those columnconfigur(...):
chart_preset_frame.columnconfigure(0, weight=6, uniform=1)
chart_preset_frame.columnconfigure(1, weight=2, uniform=1)
chart_preset_frame.columnconfigure(2, weight=2, uniform=1)
Result:

Why i can't fix the boxes alignment in Gridview on windows

there are some space between the result as you can see in the image that password entry and generate password aren't aligning together
*Result image
from tkinter import
window = Tk()
window.title("Password Manager")
window.config(padx=20, pady=20)
canvas = Canvas(width=200, height=200, highlightthickness=0)
password_image = PhotoImage(file="logo.png")
image = canvas.create_image(100, 100, image=password_image)
canvas.itemconfig(image)
canvas.grid(row=0, column=1)
website_label = Label(text="Website")
website_label.grid(row=1, column=0)
Email_username_label = Label(text="Email/Username")
Email_username_label.grid(row=2, column=0)
password_label = Label(text="Password")
password_label.grid(row=3, column=0)
website_input = Entry(width=35)
website_input.grid(row=1, column=1, columnspan=2)
Email_username_input = Entry(width=35)
Email_username_input.grid(row=2,column=1, columnspan=2)
password = Entry(width=21)
password.grid(row=3, column=1)
generate_button = Button(text="Generate Password")
generate_button.grid(row=3, column=2)
add_password_button = Button(text="Add", width=36)
add_password_button.grid(row=4, column=1, columnspan=2)
window.mainloop()
You can see that there is some space in password entry and generate password how to fix it
As noted in the comments, using the grid method allows you to just add sticky to align elements. In this case, I've removed all the width options in your entries and buttons with stick='EW' to expand East and West, or to the maximum left and right of the column the widget is in.
from tkinter import *
window = Tk()
window.title("Password Manager")
window.config(padx=20, pady=20)
# Canvas
canvas = Canvas(width=200, height=200, highlightthickness=0)
password_image = PhotoImage(file="logo.png")
image = canvas.create_image(100, 100, image=password_image)
canvas.itemconfig(image)
canvas.grid(row=0, column=1)
# Labels
website_label = Label(text="Website")
website_label.grid(row=1, column=0)
Email_username_label = Label(text="Email/Username")
Email_username_label.grid(row=2, column=0)
password_label = Label(text="Password")
password_label.grid(row=3, column=0)
# Entries
website_input = Entry()
website_input.grid(row=1, column=1, columnspan=2, sticky='EW') # sticky
Email_username_input = Entry()
Email_username_input.grid(row=2, column=1, columnspan=2, sticky='EW') # sticky
password = Entry()
password.grid(row=3, column=1, sticky='EW') # sticky
# Buttons
generate_button = Button(text="Generate Password")
generate_button.grid(row=3, column=2)
add_password_button = Button(text="Add")
add_password_button.grid(row=4, column=1, columnspan=2, sticky='EW') # sticky
window.mainloop()
You may also want to consider reading up on column and row weights using columnconfigure and rowconfigure if you want your GUI to resize dynamically.

I would like to have frames defaulted to hidden until a checkbutton is clicked

Novel was kind enough to help me with hiding a frame until a checkbutton was checked.
it worked great, when script was run frame 3 defaulted to hidden.
My problem developed when I added another function to hide frame 4.
Now when I run sript frames are no longer defaulted to hidden.
I need to check and uncheck button to hide frame(S)
I have tried bundling all if variables under 1 def and the result is the same.
My actual command frame has 21 buttons that open 21 frames and it will work with a little help.
This is well above my level, but I am willing to learn
Any help would be greatly appreciated.
I have attached a shortened version of my final file.
from tkinter import *
from tkinter import Tk
import tkinter as tk
from tkinter import ttk
root=tk.Tk()
root.title("Dental Milling Machines")
root.geometry("1000x900")
def frame3_disp():
if cb_var1.get():
frame3.grid(row=2, column=0, pady=2,sticky="NW")
else:
frame3.grid_forget()
def frame4_disp():
if cb_var2.get():
frame4.grid(row=3, column=0, pady=2,sticky="NW")
else:
frame4.grid_forget()
cb_var1 = tk.IntVar()
cb_var2 = tk.IntVar()
frame1 = Frame(root, height = 150, width= 150, relief= RAISED, bd=8, bg="blue")
frame2 = Frame(frame1, height = 150, width= 150, relief= RAISED, bd=8, bg="lightblue")
frame3 = Frame(frame1, height = 150, width= 150, relief= RAISED, bd=8, bg="lightblue")
frame4 = Frame(frame1, height = 150, width= 150, relief= RAISED, bd=8, bg="lightblue")
label = Label(frame2, text="COMMAND FRAME", fg="red")
label.grid(row=0, columnspan=3, pady= 1, sticky= "W")
label = Label(frame3, text="FRAME 3", fg="red")
label.grid(row=0, columnspan=3, pady= 1, sticky= "W")
label = Label(frame4, text="FRAME 4", fg="red")
label.grid(row=0, columnspan=3, pady= 1, sticky= "W")
frame1.grid(row=0, column=0, pady=2,sticky="NW")
frame2.grid(row=1, column=0, pady=2,sticky="NW")
frame3.grid(row=2, column=0, pady=2,sticky="NW")
frame4.grid(row=3, column=0, pady=2,sticky="NW")
c1 = Checkbutton(frame2, text = "Unhide frame3 when checked HIDE when unchecked ", variable=cb_var1, command=frame3_disp)
c1.grid(row=1, column=0, pady= 1, padx= 5, sticky= "W")
c2 = Checkbutton(frame2, text = "Unhide frame4 when checked HIDE when unchecked ", variable=cb_var2, command=frame4_disp)
c2.grid(row=2, column=0, pady= 1, padx= 5, sticky= "W")
root.mainloop()
You should not call grid(...) on frame3 and frame4 after creating them if you want them hidden initially:
import tkinter as tk
from tkinter import ttk
root=tk.Tk()
root.title("Dental Milling Machines")
root.geometry("1000x900")
def frame3_disp():
if cb_var1.get():
frame3.grid(row=2, column=0, pady=2, sticky="NW")
else:
frame3.grid_forget()
def frame4_disp():
if cb_var2.get():
frame4.grid(row=3, column=0, pady=2, sticky="NW")
else:
frame4.grid_forget()
cb_var1 = tk.IntVar()
cb_var2 = tk.IntVar()
frame1 = tk.Frame(root, height=150, width=150, relief=tk.RAISED, bd=8, bg="blue")
frame2 = tk.Frame(frame1, height=150, width=150, relief=tk.RAISED, bd=8, bg="lightblue")
frame3 = tk.Frame(frame1, height=150, width=150, relief=tk.RAISED, bd=8, bg="lightblue")
frame4 = tk.Frame(frame1, height=150, width=150, relief=tk.RAISED, bd=8, bg="lightblue")
label = tk.Label(frame2, text="COMMAND FRAME", fg="red")
label.grid(row=0, columnspan=3, pady= 1, sticky= "W")
label = tk.Label(frame3, text="FRAME 3", fg="red")
label.grid(row=0, columnspan=3, pady= 1, sticky= "W")
label = tk.Label(frame4, text="FRAME 4", fg="red")
label.grid(row=0, columnspan=3, pady= 1, sticky= "W")
frame1.grid(row=0, column=0, pady=2,sticky="NW")
frame2.grid(row=1, column=0, pady=2,sticky="NW")
#frame3.grid(row=2, column=0, pady=2,sticky="NW")
#frame4.grid(row=3, column=0, pady=2,sticky="NW")
c1 = tk.Checkbutton(frame2, text = "Unhide frame3 when checked HIDE when unchecked ", variable=cb_var1, command=frame3_disp)
c1.grid(row=1, column=0, pady= 1, padx= 5, sticky= "W")
c2 = tk.Checkbutton(frame2, text = "Unhide frame4 when checked HIDE when unchecked ", variable=cb_var2, command=frame4_disp)
c2.grid(row=2, column=0, pady= 1, padx= 5, sticky= "W")
root.mainloop()

Python Tkinter grid spacing of widgets and LablelFrames not right

I am designing a simple GUI in Python 2.7 Tkinter, but I can't get things to spread out as I want them. I have managed to get my various widgets roughly where I want them, however I can't seem to force spacing out and things are a little bunched up.
I have also tried to draw 3 LabelFrames to separate the window out, but widgets seem to fall over the LabelFrames. I am wondering how I can space this out a little better. The grid system seems to allow things to bunch up and ignores blank rows and columns as far as I can see.
from Tkinter import *
import Tkinter, Tkconstants, tkFileDialog, tkMessageBox
class FileZap():
def __init__(self, root):
root.title("TestGUI")
root.geometry("860x450")
self.topFrame = LabelFrame(root, text="Top Area")
self.topFrame.grid(row=1, column=1, rowspan=6, columnspan=7, padx=5, pady = 5, sticky="NSEW")
self.listbox1 = Listbox(root, width=50, selectmode="multiple")
self.listbox1.grid(row=3, column=2)
self.scrollbar = Scrollbar(orient=VERTICAL, command=self.listbox1.yview)
self.listbox1.config(yscrollcommand=self.scrollbar.set)
self.scrollbar.grid(row=3, column=3, sticky="ns")
self.listbox2 = Listbox(root, width=50)
self.listbox2.grid(row=3, column=4)
self.selectLabel = Label(root, text="Select a folder: ")
self.selectLabel.grid(row=3, column=1)
self.user1 = Entry(root, width="50")
self.user1.grid(row=2, column=2)
self.browse = Button(root, text="Browse")
self.browse.grid(row=2, column=3)
self.addItems = Button(root, text="Add to Selection")
self.addItems.grid(row=4, column=2)
self.clearItems = Button(root, text="Clear Selection")
self.clearItems.grid(row=4, column=4)
self.leftFrame = LabelFrame(root, text="Left Area")
self.leftFrame.grid(row=5, column=1, rowspan=6, columnspan=3, padx=5, pady = 5, sticky="NSEW")
self.replaceInLable = Label(root, text="String to replace: ")
self.replaceOutLable = Label(root, text="New string: ")
self.replaceInLable.grid(row=7, column=1)
self.replaceOutLable.grid(row=7, column=2)
self.replaceIn = Entry(root, width="20")
self.replaceOut = Entry(root, width="20")
self.replaceIn.grid(row=8, column=1)
self.replaceOut.grid(row=8, column=2)
self.replace = Button(root, text="Replace")
self.replace.grid(row=8,column=3)
self.rightFrame = LabelFrame(root, text="Right Area")
self.rightFrame.grid(row=5, column=4, rowspan=6, columnspan=3, padx=5, pady = 5, sticky="NSEW")
self.quit = Button(root, text="Exit", command=root.quit)
self.quit.grid(row=9, column=6)
root = Tkinter.Tk()
file_zap = FileZap(root)
root.mainloop()
I have tried various alterations but can't nail it! Any help would be much appreciated.
First, the columns / row adapt to there content so an empty one as a zero height/width. If you want to put space between your widgets use the padx and pady options in the .grid method. They can take either one number which will give the padding on both sides or a couple of numbers giving the padding on each side.
Secondly, if you want your widgets to be inside a LabelFrame, you need to create them with this LabelFrame as master instead of the main window.
from Tkinter import LabelFrame, Tk, Button, Label
root = Tk()
# make row 0 resize with the window
root.rowconfigure(0, weight=1)
# make column 0 and 1 resize with the window
root.columnconfigure(0, weight=1)
root.columnconfigure(1, weight=1)
# create LabelFrames
top_frame = LabelFrame(root, text="top")
left_frame = LabelFrame(root, text="left")
right_frame = LabelFrame(root, text="right")
top_frame.grid(row=0, column=0, columnspan=2, padx=10, pady=(10,4), sticky="nsew")
left_frame.grid(row=1, column=0, padx=(10,4), pady=4, sticky="nsew")
right_frame.grid(row=1, column=1, padx=(4,10), pady=4, sticky="nsew")
#create widgets inside top_frame
Label(top_frame, text="I'm inside top_frame").pack()
Button(top_frame, text="Top").pack()
#create widgets inside left_frame
Label(left_frame, text="I'm inside left_frame").pack()
Button(left_frame, text="Left").pack()
#create widgets inside top_frame
Label(right_frame, text="I'm inside right_frame").pack()
Button(right_frame, text="Right").pack()
Button(root, text="Quit", command=root.destroy).grid(row=2, column=0,
columnspan=2, pady=10)
root.mainloop()

Categories