Using tkinter grid - python

I am fairly new to using .grid in tkinter and was wondering how I could get the l2 variable to be right under the l1 variable. When the code is run the 2nd label is too far down (even have to resize window). I would like to be able to place it in a specific place (below l1) but I'm not sure how to.
Thank you.
Example:
Welcome
Please log-in to continue
Gap's a little big there as well.
Current code:
from tkinter import *
from tkinter.ttk import *
root = Tk()
root.geometry("1300x720")
myImage = PhotoImage(file='ssf.png')
label = Label(image=myImage)
label.grid(row=0)
label.image = myImage
l1 = Label(root, text="Welcome", font="Arial 100 bold", anchor="e").grid(row=0, column=1)
l2 = Label(root, text="Please log-in to continue.", font="Arial 30 bold", anchor="e").grid(row=10, column=1)
Preview of how it looks

Well, you can use the Frame widget to put the text in it like this:
from tkinter import *
from tkinter.ttk import *
root = Tk()
root.geometry("1300x720")
myImage = PhotoImage(file='ssf.png')
label = Label(image=myImage)
label.grid(row=0)
label.image = myImage
labelFrame = Frame(root)
labelFrame.grid(row=0,column=1)
l1 = Label(labelFrame, text="Welcome", font="Arial 100 bold", anchor="e")
l1.grid(row=0, column=0)
l2 = Label(labelFrame, text="Please log-in to continue.", font="Arial 30 bold", anchor="e")
l2.grid(row=1, column=0)
The Frame widget is in row 0, column 1 and contains 'l1' and 'l2'.

Pls see my comments in the revised code below.
I would recommend drawing out the grid system on paper to visualise
your layout and compare it with what is created by your program.
Activating the background color of the widgets such as frame and
label will help you visualize your creation.
Recommend reading these references.
http://www.tkdocs.com/tutorial/grid.html
http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/layout-mgt.html
Happy coding. :)
#from tkinter import *
#from tkinter.ttk import *
## I suggest you abbreviate the imported modules to help you keep track of which
## module methods/functions you are using. See below. To be consistent, we will
## use ttk widgets where possible.
# Load tkinter for python 3
import tkinter as tk
import tkinter.ttk as ttk
root = tk.Tk()
root.geometry("1300x720")
# Customise style of ttk widgets
# I have added this to help you visualise the grid system.
s=ttk.Style()
s.configure('frame1.TFrame', background='pink')
s.configure('l0.TLabel', background='blue')
s.configure('l1.TLabel', background='green')
s.configure('l2.TLabel', background='brown')
# Create a frame inside root to contain all the widgets.
# The frame contains a 2x2 grid.
frame1 = ttk.Frame(root, style='frame1.TFrame', borderwidth=20, relief=tk.SUNKEN )
frame1.grid(row=0, column=0, rowspan=2, columnspan=2, sticky='nsew')
# Load Image
# Added tk in fromt of PhotoImage.
myImage = tk.PhotoImage(file='ssf.png')
# Create a ttk.label to contain image
## I added ttk in front of Label. If not, it will mean you will use tk.Label instead of ttk.Label.
## Also I added frame1 as the 1st option to the ttk.Label to mean the ttk.Label
## is inside frame1.
## The "in_=frame1" option is added to grid to mean l0 is grid inside frame1 grid system.
l0 = ttk.Label(frame1, image=myImage, width=500)
l0.grid(in_=frame1, row=0, column=0, sticky='nsew')
#label.image = myImage
# Create a ttk.Label to contain l1
l1 = ttk.Label(frame1, text="Welcome", style='l1.TLabel', font="Arial 100 bold", anchor=tk.E)
l1.grid(in_=frame1, row=0, column=1)
#l1 = Label(root, text="Welcome", font="Arial 100 bold", anchor="e").grid(row=0, column=1)
# Create a ttk.Label to contain l2
l2 = ttk.Label(frame1, text="Please log-in to continue.", style='l2.TLabel', font="Arial 30 bold")
l2.grid(in_=frame1, row=1, column=1)
#l2 = Label(root, text="Please log-in to continue.", font="Arial 30 bold", anchor="e").grid(row=10, column=1)
# These configuration settings will let the grid columns and rows scale according
# to the changing size of the Window i.e. root.
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
frame1.rowconfigure(0, weight=1)
frame1.columnconfigure(1, weight=1)

Related

How should I change my tkinter code to rearrange the elements on my page?

I'm learning tkinter and getting stumped in one area. Here's the code:
from tkinter import *
from tkinter.messagebox import showinfo
def button_press():
showinfo('info','pressed button')
root = Tk()
root.geometry('800x500')
f = Frame(root)
f.pack()
Label(f, text="this is a line of text").pack(side=LEFT)
s = StringVar(value='enter here')
Entry(f, textvariable=s, width=100).pack(side=LEFT)
Button(f, text='Button', command=button_press).pack(side=RIGHT)
root.mainloop()
It produces:
But I want to align the text vertically with the entry field like this:
What do I need to change to make that happen?
Using .pack() is not advisable if you want to create more complex Frame structures.
Instead assign the items to variables and place those into a .grid().
.grid splits up your frame into different rows and columns or "sticks" them on a certain place.
below an example:
from tkinter import *
from tkinter.messagebox import showinfo
def button_press():
showinfo('info', 'pressed button')
root = Tk()
root.geometry('800x500')
f = Frame(root)
f.pack()
l1 = Label(f, text="this is a line of text")
l1.grid(row=1, column=1, sticky=W)
s = StringVar(value='enter here')
entry = Entry(f, textvariable=s, width=100)
entry.grid(row=2, column=1)
button = Button(f, text='Button', command=button_press)
button.grid(row=2, column=2)
root.mainloop()

How to make text show up in a specific location on a Tkinter window

please see the code below. Working on a 100 days of code project. How to I make text appear in a specific position (x=400, y=150) for example on a window.
Please see my code below.
from tkinter import *
from tkinter import messagebox
BACKGROUND_COLOR = "#B1DDC6"
window = Tk()
window.title('Flashy')
window.config(padx=50, pady=50, bg=BACKGROUND_COLOR)
# Todo. Center the front of the card.
canvas = Canvas(width=800, height=526, bg=BACKGROUND_COLOR, highlightthickness=0)
card_front = PhotoImage(file='images/card_front.png')
canvas.create_image(400, 263, image=card_front)
canvas.grid(row=0, column=1, columnspan=2)
# Placing text on the card.
text_1 = Label(text="French", bg='white', font=("Ariel", 40, "italic"), fg='black')
text_1.goto(x=400, y=150)
text_1.grid(row=0, column=0, columnspan=2)
# Buttons
check_mark = PhotoImage(file='images/right.png')
check_mark_button = Button(image=check_mark, highlightthickness=0)
check_mark_button.grid(row=1, column=2)
wrong_mark = PhotoImage(file='images/wrong.png')
wrong_mark_button = Button(image=wrong_mark, highlightthickness=0)
wrong_mark_button.grid(row=1, column=1)
window.mainloop()
I tried using .config to specify the location for the text but that doesn't work.
Use the place() geometry manager to place widgets at specific coordinates.
Instead of:
text_1.goto(x=400, y=150)
Try...
text_1.place(x=400, y=150)
And remove:
text_1.grid(row=0, column=0, columnspan=2)
since you should only use one geometry manager method (pack, grid, or place) on a given widget.

Scrolled Text in Tkinter (scrollbar issue) with .grid()

I'm having some issues with a ScrolledText widget in tkinter.
The Scrollbar is not showing up.
Here is my code:
from tkinter import *
import os
from tkinter.scrolledtext import ScrolledText
#window variables
win = Tk()
win.title('TextS')
win_width = 600
win_height = 400
win.geometry('{}x{}'.format(win_width,win_height))
#widgets
title = Label(win, text="TextS", font=("Helvetica", 36, "bold"), bg="lightgray")
title.grid(row=0, column=0)
st = ScrolledText(win, width=400, height=300)
st.grid(column=1, pady=10, padx=10)
#main loop
while True:
win.update()
Some Screen Shots:
With .grid() what I want to use:
screenshot
With .pack() which I do not want to use:
screenshot
(Has scroll bar)
Sorry if this is a noobie mistake,
Thank you!
Have a great day! :)
ScrolledText uses width and height in chars, not in pixels - so you create very big widget and scroller doesn't fit in window. You have to use smaller values.
grid doesn't use free space when you resize (all of them use value weight=0. You have to use bigger weight to inform which row and column has to use this free space when you resize.
win.grid_columnconfigure(1, weight=1) # column 1
win.grid_rowconfigure(1, weight=1) # row 1
Now it will resize cells in row 1 and column 1 but it doesn't resize widgets in cells. Widgets needs grid(..., sticky='nsew') to resize in all directions.
import tkinter as tk # PEP8: `import *` is NOT preferred
from tkinter.scrolledtext import ScrolledText
# window variables # PEP8: one space after `#`
win = tk.Tk()
win.grid_columnconfigure(1, weight=1)
win.grid_rowconfigure(1, weight=1)
title = tk.Label(win, text="TextS", font=("Helvetica", 36, "bold"), bg="lightgray")
title.grid(row=0, column=1)
st = ScrolledText(win, width=100, height=25)
st.grid(column=1, pady=10, padx=10, sticky='nsew')
# main loop
win.mainloop()
PEP 8 -- Style Guide for Python Code
Using same code.
set geometry to 350x300
In line 20 set ScrolledText to width=40, height=10
Set column to 0 not 1
You're set to go.
Code:
from tkinter import *
import os
from tkinter.scrolledtext import ScrolledText
#window variables
win = Tk()
win.title('TextS')
win_width = 600
win_height = 400
win.geometry('350x300')
#widgets
title = Label(win, text="TextS", font=("Helvetica", 36, "bold"), bg="lightgray")
title.grid(row=0, column=0)
st = ScrolledText(win, width=40, height=10)
st.grid(column=0, pady=10, padx=10)
#main loop
while True:
win.update()
win.mainloop()
Screenshot output:

Tkinter how to size fonts and keep alignment

I'm writing an app that needs to be zoomable. Using the default system fonts, "TkDefaultFont and TkTextFont" I increase their sizes and I get the results I want sort of. The problem is after sizing the alignment is thrown off between the field label and field widget. I have tried applying update_idletasks() but it does nothing. Moving the mouse over the widget fixes the problem as see in the video. If you run the example below go the the size spinbox and change the size to view the issue.
My dev system is Linux, Desktop KDE, I don't know if this is a OS issue.
A link to a short video of the issue.
Video of Alignment Issue.
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.font as tkfont
root = tk.Tk()
root.rowconfigure(0, weight=1)
root.columnconfigure(99, weight=1)
frame = ttk.Frame(root)
frame.rowconfigure(0, weight=1)
frame.columnconfigure(0, weight=1)
cbo = ttk.Combobox(frame)
cbo.config(
values=('Test 1', 'Test 2', 'Test 3')
)
cbo.set(value='Test 1')
ent_var = tk.StringVar()
ent = ttk.Entry(frame, textvariable=ent_var)
ent_var.set('Test')
lb_size = ttk.Label(frame, text='size')
spn = ttk.Spinbox(frame, values=tuple(range(1, 101)))
font1 = tkfont.nametofont('TkDefaultFont')
font2 = tkfont.nametofont('TkTextFont')
lbl_field_name = tk.Label(frame, text='Field Name')
lbl_field_name.grid()
def size(e):
cfg = font1.actual()
cfg['size'] = e.widget.get()
font1.configure(**cfg)
font2.configure(**cfg)
spn.bind('<<Increment>>', size)
spn.bind('<<Decrement>>', size)
cbo.grid(row=0, column=1, sticky=tk.NSEW)
ent.grid(row=0, column=2, sticky=tk.NSEW)
lb_size.grid(row=0, column=3, sticky=tk.NSEW)
spn.grid(row=0, column=4, sticky=tk.NSEW)
frame.grid(sticky=tk.NSEW)
root.mainloop()
The only way I have found to avoid this issue is to change the font from each entry's configure() method. I guess the easier way will be to put all the entries in a list, see code below.
I have also noticed that size() uses the previous value of the spinbox not the one after the increment/decrement. To avoid that, I suggest you to use the command option of the spinbox instead of the bindings to <<Increment>> and <<Decrement>> (see code below).
Finally, you do not need to retrieve the whole font settings to update the size, you can simply do font1.configure(size=<newsize>).
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.font as tkfont
root = tk.Tk()
root.rowconfigure(0, weight=1)
root.columnconfigure(99, weight=1)
frame = ttk.Frame(root)
frame.rowconfigure(0, weight=1)
frame.columnconfigure(0, weight=1)
entries = [] # list of all entries
cbo = ttk.Combobox(frame)
cbo.config(
values=('Test 1', 'Test 2', 'Test 3')
)
cbo.set(value='Test 1')
entries.append(cbo)
ent_var = tk.StringVar()
ent = ttk.Entry(frame, textvariable=ent_var)
ent_var.set('Test')
entries.append(ent)
def size():
size = spn.get() # get current spinbox's value
font1.configure(size=size)
font2.configure(size=size)
for e in entries: # update font in all entries
e.configure(font=font2)
lb_size = ttk.Label(frame, text='size')
# use the command option to update the font size
spn = ttk.Spinbox(frame, command=size, values=tuple(range(1, 101)))
font1 = tkfont.nametofont('TkDefaultFont')
font2 = tkfont.nametofont('TkTextFont')
lbl_field_name = ttk.Label(frame, text='Field Name')
lbl_field_name.grid()
cbo.grid(row=0, column=1, sticky=tk.NSEW)
ent.grid(row=0, column=2, sticky=tk.NSEW)
lb_size.grid(row=0, column=3, sticky=tk.NSEW)
spn.grid(row=0, column=4, sticky=tk.NSEW)
frame.grid(sticky=tk.NSEW)
root.mainloop()

Expand a listbox over 2 columns Tkinter

I have the following interface: 3 frames from which 2 are on the left-hand, frame1 and frame2 and another one which is on the right, frame3.
I want to create another frame, frame4 which will have the label Output and under it there should be a Listbox. I want that both these widgets to span over the previous frames, each being places in a cell by using the grid manager.
Also I am not sure if Listbox is the widget I should be using. I want something which will contain the output of the program I will run through my application. I also thought of Entry but I need something in which I can display more than one line.
This is the code I have so far:
from Tkinter import *
root = Tk()
frame1 = Frame(root)
frame1.grid(row=0,column=0)
frame2 = Frame(root)
frame2.grid(row=1,column=0)
frame3 = Frame(root)
frame3.grid(row=0,column=1)
frame4 = Frame(root)
frame4.grid(row=2,columnspan=2)
l5 = Label(frame4, text='Output:').grid(row=2,columnspan=2)
output = Listbox(frame4, height=5)
#output.grid(row=2,column=0,columnspan=2)
#output.pack(side=LEFT, fill=BOTH, expand=1)
root.mainloop()
I managed to make the label to span across the other frames, but when I uncommented either of the last 2 lines, the interface didn't open and the program just froze.
How can I solve this?
I slightly ammended your code:
from tkinter import * # for python 2.7 use Tkinter
root = Tk()
frame1 = Frame(root, bg='red', height=20)
frame1.grid(row=0,column=0, sticky=W+E)
frame3 = Frame(root, bg='blue', height=20)
frame3.grid(row=0,column=1, sticky=W+E)
frame2 = Frame(root, bg='green', height=20)
frame2.grid(row=1,column=0, sticky=W+E)
frame4 = Frame(root)
frame4.grid(row=2,columnspan=2, sticky=E+W)
l5 = Label(frame4, text='Output:', bg='orange').grid(row=0, column=0, sticky=E+W)
output = Listbox(frame4, height=5, width=50)
output.grid(row=1,column=0)
#output.pack(side=LEFT, fill=BOTH, expand=1)
root.mainloop()
This results in:
So basically what I did was to add bg, height and sticky parameters to frames and label to easily visual what is happening and how they frames are laid out. Also I modified grid parameters listbox and label.
Hope this is what you are after, or it will help you to get there.
If you use both .grid() and .pack() Tkinter (python 2.x) or tkinter (python 3.x) will happily spend the rest of your life trying to find a way to satisfy both, you must use one within the same window or Frame, see http://www.openbookproject.net/py4fun/gui/tkPhone.html

Categories

Resources