I've structured this post into four parts, the goal of what I'm trying to achieve, the minimal amount of code to recreate the problem, things I have already tried, and a conclusion. The code provided will look like this.
Goal:
Using Python Tkinter, set up a canvas to be able to scroll through tk.Entry widgets that are off-screen without the use of a scrollbar. The idea is to eventually lead up to being able to set a root.after to animate the scroll automatically without user input. I'm trying my best not to use a scrollbar as the end result will be a results list for a competition, so it's purely for viewing rather than interaction.The minimum amount of code to recreate:
(The test data is just long enough to have the last few Entries be off-screen when the geometry is 1920x1080)# Python program to create a table
import tkinter as tk
from tkinter import ttk
from ESTDisplayEntity import ESTDisplayEntity
root = tk.Tk()
root.geometry("1920x1080")
class Table():
def __init__(self, root, lst):
self.Tree = ttk.Treeview(root)
# find total number of rows and
# columns in list
total_rows = len(lst)
total_columns = len(lst[0])
maxWidth = 125
# code for creating table
for i in range(total_rows):
for j in range(total_columns):
if j == 0:
width = int(maxWidth*.05)
elif j == 1:
width = int(maxWidth*.25)
elif j == 2:
width = int(maxWidth*0.15)
else:
width = int(maxWidth*(.15/total_columns-3))
e = tk.Entry(self.Tree, width=width, fg='Black',
font=('Arial',16,'bold'))
e.grid(row=i, column=j, sticky = "EW")
e.insert(tk.END, lst[i][j])
e.configure(state="readonly")
self.Tree.grid_columnconfigure(0, weight=0)
self.Tree.grid_columnconfigure(1, weight=3)
self.Tree.grid_columnconfigure(2, weight=2)
for i in range(total_columns-3):
self.Tree.grid_columnconfigure(i+3, weight = 1)
# test data
lest = [
(1,'Raj Mumbai'," Rifle",19,15,250,400),
(2,'Aaryan Pune'," Rifle",18,100,300,500),
(3,'Vaishnavi Mumbai'," Rifle",20,155,300,560),
(4,'Rachna Mumbai'," Rifle",21,125,300,450),
(4,'Rachna Mumbai'," Rifle",21,125,300,450),
(4,'Rachna Mumbai'," Rifle",21,125,300,450),
(5,'Rachna Mumbai'," Rifle",21,125,300,450),
(5,'Rachna Mumbai'," Rifle",21,125,300,450),
(5,'Rachna Mumbai'," Rifle",21,125,300,450),
(5,'Rachna Mumbai'," Rifle",21,125,300,450),
(5,'Rachna Mumbai'," Rifle",21,125,300,450),
(5,'Rachna Mumbai'," Rifle",21,125,300,450),
(5,'Rachna Mumbai'," Rifle",21,125,300,450),
(13,'Shubham Delhi'," Rifle",21,122,300,741),
(14,'Shubham Delhi'," Rifle",21,122,300,741),
(14,'Shubham Delhi'," Rifle",21,122,300,741),
(14,'Shubham Delhi'," Rifle",21,122,300,741),
(14,'Shubham Delhi'," Rifle",21,122,300,741),
(14,'Shubham Delhi'," Rifle",21,122,300,741),
(14,'Shubham Delhi'," Rifle",21,122,300,741),
(14,'Shubham Delhi'," Rifle",21,122,300,741),
(15,'Shubham Delhi'," Rifle",21,122,300,741),
(15,'Shubham Delhi'," Rifle",21,122,300,741),
(15,'Shubham Delhi'," Rifle",21,122,300,741),
(15,'Shubham Delhi'," Rifle",21,122,300,741),
(16,'Shubham Delhi'," Rifle",21,122,300,741),
(16,'Shubham Delhi'," Rifle",21,122,300,741),
(16,'Shubham Delhi'," Rifle",21,122,300,741),
(16,'Shubham Delhi'," Rifle",21,122,300,741),
(17,'Shubham Delhi'," Rifle",21,122,300,741),
(17,'Shubham Delhi'," Rifle",21,122,300,741),
(17,'Shubham Delhi'," Rifle",21,122,300,741),
(17,'Shubham Delhi'," Rifle",21,122,300,741),
(18,'Shubham Delhi'," Rifle",21,122,300,741),
(18,'Shubham Delhi'," Rifle",21,122,300,741),
(19,'Shubham Delhi'," Rifle",21,122,300,741),
(19,'Shubham Delhi'," Rifle",21,122,300,741),
(19,'Shubham Delhi'," Rifle",21,122,300,741),
(19,'Shubham Delhi'," Rifle",21,122,300,741)
]
topframe = tk.Frame(root)
topframe.pack(fill=tk.X)
scrollingFrame = tk.Canvas(root)
scrollingFrame.pack(fill=tk.BOTH)
t = Table(scrollingFrame, lest)
t.Tree.pack(fill=tk.BOTH)
# SB = tk.Button(topframe, command=t.Tree.yview_moveto(fraction=50), text= "TWSTF")
SB = tk.Button(topframe, command=scrollingFrame.yview_moveto(fraction=50), text= "TWSTF")
SB.pack()
root.mainloop()
Things I have tried:
- Tried modifying self.Tree to be a Listbox in order to follow Volting's advice. When using Volting's code, it did not produce the desired result as instead, it's more of a "following" scroll rather than my desired effect. Plus it adds a scrollbar, which isn't apart of my design.
- I've tried creating a method called "scroll" that does the same thing as the button in my example code and calling it after the Table has been populated. Same results as the button, nothing happened.
- Modifying self.Tree to be a Listbox (again...) and then using the Listbox.see method so try and move the view to the end of the list box. Similar to this question and answer.
- Setting Canvas.yview_moveto() and yview_scroll() to a button and a method, similar to this question. It produced the same effect as the current minimum amount of code, nothing happened.