Reputation: 329
I made an Excel-like grid for entering data that will be exported to another program. The top row is "frozen" so that it remains visible when you scroll down. I'm using a list ColWidths = [15, 15, 40]
to define the widths of the widgets in the top row, and the widgets in the scroll-able rows beneath.
I read that if you don't give a unit, width
defaults to pixels. Even so, I made sure to use the same font size in the top row and all the other rows.
Oddly the columns still appear to be slightly different widths. Any idea how to fix this?
MCVE CODE:
import tkinter as tk
from tkinter import simpledialog,filedialog,colorchooser,messagebox,Frame,Button
from PIL import ImageTk, Image
import textwrap
root = tk.Tk()
canv_1 = tk.Canvas(root, bg="blue")
canv_1.pack(side="top", fill="both")#, fill="both", expand=True)
canv_2 = tk.Canvas(root, bg="gray")
canv_2.pack(fill="both", expand=True)
def onFrameConfigure(canvas):
'''Reset the scroll region to encompass the inner frame'''
canvas.configure(scrollregion=canvas.bbox("all"))
frame = tk.Frame(canv_2)
# create, bind & position scrollbar
vsb = tk.Scrollbar(canv_2, orient="vertical", command=canv_2.yview)
canv_2.configure(yscrollcommand=vsb.set)
vsb.pack(side="right", fill="y")
canv_2.pack(side="left", fill="both", expand=True)
canv_2.create_window((0,0), window=frame, anchor="nw")
frame.bind("<Configure>", lambda event, canv_2=canv_2: onFrameConfigure(canv_2))
labels = ["Chapter Title", "Slide", "Instructions"]
ColWidths = [15, 15, 40]
root.label_wid = []
font1 = ("arial", 15, "bold")
load1 = Image.open("StartingImage.jpg")
root.render1 = ImageTk.PhotoImage(load1)
ch_text = []
for i in range(len(labels)):
root.label_wid.append(tk.Label(canv_1,
font=font1,
relief="raised",
text=labels[i],
width=ColWidths[i],
).grid(row=0, column=i, sticky="we"))
c1 = "#a9d08e"
c2 = "#8dd1bf"
Title_col = [
tk.Entry(
frame,
bg = c1,
width = ColWidths[0],
font = font1)
for y in range(0, 5)
]
Slide_col = [
tk.Entry(
frame,
bg = c2,
width = ColWidths[1],
font = font1)
for y in range(0, 5)
]
instruction_col = [
tk.Text(
frame,
bg="white",
wrap="word",
font=font1, width = ColWidths[2], height=10)
for y in range(0, 5)
]
for y in range(0, 5):
Title_col[y].grid(row=y + 1, column=0, sticky='news')
Slide_col[y].grid(row=y + 1, column=1, sticky='news')
instruction_col[y].grid(row=y+1, column=2, sticky='news')
bt1 = tk.Button(canv_1, text="Export", font=font1, bg="#f5b942")
bt1.grid(row=0, column=4)
load2 = Image.open("scroll-up-gray.png")
root.render2 = ImageTk.PhotoImage(load2)
load3 = Image.open("scroll-down.png")
root.render3 = ImageTk.PhotoImage(load3)
root.mainloop()
Upvotes: 1
Views: 527
Reputation: 5531
Remove bold
from your font or figure out how much to add to the image column (your original screen grab) to compensate. Seriously though, just remove bold
from your font and watch it all magically work.
bold
is adding extra pixels to all of your labels, and it isn't adding anything in all of those empty boxes. It took me like 2 hours to figure this out (lol)! I even rewrote your entire example much better and still couldn't get it to work ... until I realized that the instruction label was being forced out of the window bounds. Some kind of way that triggered the font format in my head. I simply removed bold
and everything worked. I then re-copy/pasted your example and removed bold
. It still worked.
I understand that you ultimately want to keep bold
. You will have to use line-metrics or something more reliable than simply telling every column to be the same size. The main point is, at least now you know the culprit and why.
edit:
I also got it to work by doing the below instead. Unfortunately, I can't explain why this works. Obviously, I know that we are just adding an inner padding to each cell, but I don't understand why dividing the cell width by 2 works in every case. This may even cause problems later. I simply don't know, but in this example case it seems to work almost perfect.
for y in range(0, 5):
Title_col[y].grid(row=y + 1, column=0, sticky='news', ipadx=ColWidths[0]/2)
Slide_col[y].grid(row=y + 1, column=1, sticky='news', ipadx=ColWidths[1]/2)
instruction_col[y].grid(row=y+1, column=2, sticky='news', ipadx=ColWidths[2]/2)
edit 2:
If you want the results of the above code to appear absolutely perfect in line with the header columns, specify highlightthickness=0
in your canvas instances. This will remove the canvas borders, which are creating a tiny offset.
canv_1 = tk.Canvas(root, bg="blue", highlightthickness=0)
canv_1.pack(side="top", fill="both")#, fill="both", expand=True)
canv_2 = tk.Canvas(root, bg="gray", highlightthickness=0)
canv_2.pack(fill="both", expand=True)
Upvotes: 1