why can't i populate my tksheet table row? - python

I am trying to get a students attendance record set up in python. I have most of it figured out. I am stuck on one section and it is the attendane section. I am trying to use a table format (tksheets) to keep record of students names and their attendance. The issue I am having is working with tksheets. I can't seem to get the information from my DB(SQLite3) to populate the columns. I've also tried tktables, and the pandastables. But again I run into the same issue.
I have considered using the Treeview Widget to populate the columns with the students names, and then use entry boxes to add the attendance. The issue is I have to create each entry box and place it individually. I didn't like this plan. Below is the current code I am using.
If anyone could show me how to get the data from the DB and populate the spreadsheet I am using that be great. Thanks.
def rows(self):
self.grid_columnconfigure(1, weight=1)
self.grid_rowconfigure(1,weight=1)
self.sheet = Sheet(self.aug_tab,
data=[[f'Row{r} Column{c}' for c in range(36)]for r in range(24)],
height=300,
width=900)
self.sheet.enable_bindings(("single",
"drag_select",
"column_drag_and_drop",
"row_drag_and_drop",
"column_select",
"row_select",
"column_width_resize",
"double_click_column_resize",
"row_width_resize",
"column_height_resize",
"arrowkeys",
"row_height_resize",
"double_click_row_resize",
"right_click_popup_menu",
"rc_insert_column",
"rc_delete_column",
"rc_insert_row",
"rc_delete_row",
"copy",
"cut",
"paste",
"delete",
"undo",
"edit_cell"))
self.headers_list = ("Student ID","Ch. First Name","Ch. Last Name","Eng. Name")
self.headers = [f'{c}'for c in self.headers_list]
self.sheet.headers(self.headers)
self.sheet.pack()
print(self.sheet.get_column_data(0,0))
#############DEFINE FUNCTIONS###############################
rows(self)
enter image description here

"""if you want to take data from your database then you must make a main frame and add the button, then make your demo tksheet function as a top level frame, i have made one my own to open my data base, all do you need is change the database in my code with your database. this is my code"""
import tkinter as tk
import datetime as dt
from tkinter import ttk
def open_window1():
from tksheet import Sheet
import tkinter as tk
import sqlite3
conn= sqlite3.connect('toko.db')
c= conn.cursor()
class demo(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.grid_columnconfigure(0, weight = 1)
self.grid_rowconfigure(0, weight = 1)
self.sheet_demo = Sheet(self,
height = 500,
width = 700)
self.sheet_demo.enable_bindings(("single",
"drag_select",
"column_drag_and_drop",
"column_select",
"row_select",
"arrowkeys",
"column_width_resize",
"row_width_resize",
"copy",
"rc_insert_column",
"rc_insert_row"))
self.sheet_demo.grid(row = 0, column= 0, sticky= "nswe")
self.headers= ("id","Produk","Stok","Harga Grosir","Harga Eceran")
self.sheet_demo.headers(self.headers)
c.execute("SELECT * FROM StokDanHarga")
h=len(c.fetchall())
print(h)
self.data =[[f"Row {r} Column {c}" for c in range(3)] for r in range(h)]
self.sheet_demo.data_reference(self.data)
a=c.execute("SELECT * FROM StokDanHarga")
j=0
for row in a:
# i= len(a)
r=j
print(r,j)
self.sheet_demo.set_row_data(r, values = row)
j += 1
app= demo()
app.mainloop()
root= tk.Tk()
root.title("combobox")
root.geometry("400x400")
buttn = ttk.Button(root, text='STOK DAN HARGA', command=open_window1)
buttn.grid(row=0, column=0)
root.mainloop()

"""well you should make a function into your code and a button, while you can insert your student name one by one or copy bulk of yor students name into the sheet, this is my code"""
from tksheet import Sheet
import tkinter as tk
class demo(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.grid_columnconfigure(0, weight = 1)
self.grid_rowconfigure(0, weight = 1)
self.sheet_demo = Sheet(self,
height = 500,
width = 700)
self.sheet_demo.enable_bindings(("single",
"drag_select",
"column_drag_and_drop",
"row_drag_and_drop",
"column_select",
"row_select",
"column_width_resize",
"double_click_column_resize",
"row_width_resize",
"column_height_resize",
"arrowkeys",
"row_height_resize",
"double_click_row_resize",
"right_click_popup_menu",
"rc_insert_column",
"rc_delete_column",
"rc_insert_row",
"rc_delete_row",
"copy",
"cut",
"paste",
"delete",
"undo",
"edit_cell"))
self.sheet_demo.grid(row = 0, column = 0, sticky = "nswe")
self.data = [[f"" for c in range(1)] for r in range(100)]
self.sheet_demo.data_reference(self.data)
def click_this():
for i in (self.sheet_demo.get_column_data(0)):
if i == '':
break
else:
print(i.strip())
self.data = [[f"" for c in range(1)]for r in range(100)]
self.sheet_demo.data_reference(self.data)
button=tk.Button(text=" click this",command= click_this)
button.grid(row= 1, column=0, sticky= "n")
app = demo()
app.mainloop()

Related

'MultiColumnListbox' object has no attribute 'curselection'

I am running into an error with my MultiColumnListbox. I am trying to understand how to fix this issue. I am trying to see what is selected in my multicolumn listbox. The mutlicolumn listbox is built using tkinter and has a submit button which should run a function telling me what rows were selected in the multi column listbox. I am receiving this error 'MultiColumnListbox' object has no attribute 'curselection' and cant seem to fix it.
This is my code
import os
import time
import glob
import datetime
from array import *
try:
import Tkinter as tk
import tkFont
import ttk
except ImportError: # Python 3
import tkinter as tk
import tkinter.font as tkFont
import tkinter.ttk as ttk
class MultiColumnListbox(object):
"""use a ttk.TreeView as a multicolumn ListBox"""
def submitFunction():
selection = listbox.curselection()
for k in range(0,len(selection)):
selected = listbox.curselection()[k]
def __init__(self):
self.tree = None
self._setup_widgets()
self._build_tree()
def _setup_widgets(self):
s = """\click on header to sort by that column
to change width of column drag boundary
"""
msg = ttk.Label(wraplength="4i", justify="left", anchor="n",
padding=(10, 2, 10, 6), text=s)
msg.pack(fill='x')
container = ttk.Frame()
container.pack(fill='both', expand=True)
# create a treeview with dual scrollbars
self.tree = ttk.Treeview(columns=car_header, show="headings")
vsb = ttk.Scrollbar(orient="vertical",
command=self.tree.yview)
hsb = ttk.Scrollbar(orient="horizontal",
command=self.tree.xview)
self.tree.configure(yscrollcommand=vsb.set,
xscrollcommand=hsb.set)
self.tree.grid(column=0, row=0, sticky='nsew', in_=container)
vsb.grid(column=1, row=0, sticky='ns', in_=container)
hsb.grid(column=0, row=1, sticky='ew', in_=container)
container.grid_columnconfigure(0, weight=1)
container.grid_rowconfigure(0, weight=1)
def _build_tree(self):
for col in car_header:
self.tree.heading(col, text=col.title(),
command=lambda c=col: sortby(self.tree, c, 0))
# adjust the column's width to the header string
self.tree.column(col,
width=tkFont.Font().measure(col.title()))
for item in car_list:
self.tree.insert('', 'end', values=item)
# adjust column's width if necessary to fit each value
for ix, val in enumerate(item):
col_w = tkFont.Font().measure(val)
if self.tree.column(car_header[ix],width=None)<col_w:
self.tree.column(car_header[ix], width=col_w)
def sortby(tree, col, descending):
"""sort tree contents when a column header is clicked on"""
# grab values to sort
data = [(tree.set(child, col), child) \
for child in tree.get_children('')]
# if the data to be sorted is numeric change to float
#data = change_numeric(data)
# now sort the data in place
data.sort(reverse=descending)
for ix, item in enumerate(data):
tree.move(item[1], '', ix)
# switch the heading so it will sort in the opposite direction
tree.heading(col, command=lambda col=col: sortby(tree, col, \
int(not descending)))
FilesToDeleteName = [];
FilesToDeletePath = [];
FilesToDeleteDate = [];
car_list = [];
car_list.append([])
car_list.append([])
#str1 = input("Enter number of days old: ")
#days = int(str1)
days = 90
count = 0
time_in_secs = time.time() - (days * 24 * 60 * 60)
extf = ['Windows','Program Files', 'Program Files (x86)']
for (root, dirs, files) in os.walk('C:/Users', topdown=True):
dirs[:] = [d for d in dirs if d not in extf]
for filename in files:
Fullname = os.path.join(root,filename)
stat = os.stat(Fullname)
modified = datetime.datetime.fromtimestamp(stat.st_mtime)
if Fullname.endswith('.pcapng') or Fullname.endswith('.evtx') or Fullname.endswith('.png') or Fullname.endswith('.sql') or Fullname.endswith('.etl') or Fullname.endswith('.zip'):
if stat.st_mtime <= time_in_secs:
FilesToDeleteName.append(filename);
FilesToDeletePath.append(Fullname);
FilesToDeleteDate.append(str(modified));
FilesToDelete = [];
for p in range(0,len(FilesToDeletePath)):
STR2 = FilesToDeletePath[p],FilesToDeleteDate[p]
FilesToDelete.append(STR2)
car_list = FilesToDelete
car_header = ["Path ", "Date Modified"]
if __name__ == '__main__':
window = tk.Tk()
window.title("Multicolumn Treeview/Listbox")
listbox = MultiColumnListbox()
def submitFunction():
print(listbox.curselection(self))
window.destroy()
def closeFunction():
window.destroy()
submit = tk.Button(window, text='Submit', command=submitFunction)
submit.pack(side=tk.RIGHT, padx = 20)
close = tk.Button(window, text='Close', command=closeFunction)
close.pack(side=tk.RIGHT)
window.mainloop()
This is the main part of my issue
def submitFunction():
print(listbox.curselection(self))
window.destroy()
I will ultimately be trying to get the index numbers to delete the given file path

is there a way to grid an extra button while running your program in tkinter correctly?

I'm making an mp3 player app and I want the user to be able to add playlists (which will be buttons in a grid system.
Like so.
However in this state when I'm trying to add a playlist button this happens:
The top buttons and the button i just added get squeezed off and the scrollbar is stuck (I can't use it)
I've tried refreshing by self.playlist_frame.update_idletasks() after running create_playlists() but it doesn't seem to change anything
this is my code so you can test it:
import os
import tkinter as tk
from tkinter import ttk
from PIL import Image, ImageTk
class MyApp:
def __init__(self):
self.root = tk.Tk()
self.width = self.root.winfo_screenwidth()
self.height = self.root.winfo_screenheight()
self.height = self.root.winfo_screenheight() - int(self.height / 13)
self.root.geometry(f'{self.width}x{self.height}')
self.root.title("Mp3")
self.c = '#14141D'
self.playlists_buttons_list = []
self.playlists = {}
self.helping_d = {}
self.main = ttk.Notebook(self.root)
self.playlists_tab = tk.Frame(self.main)
self.playlist_menu_frame = tk.Frame(self.playlists_tab, bg=self.c)
self.playlists_canvas = tk.Canvas(self.playlists_tab, bg=self.c)
self.playlist_frame = tk.Frame(self.playlists_canvas, bg=self.c)
self.playlists_scrollbar = ttk.Scrollbar(self.playlists_tab, orient='vertical',
command=self.playlists_canvas.yview)
self.add_playlist_win = tk.Toplevel(self.root)
self.add_playlists_button = tk.Button(self.playlist_frame)
self.default_img = Image.open('images/default.png').resize((75, 72))
self.default_img = ImageTk.PhotoImage(self.default_img)
self.add_img = Image.open('images/add.png').resize((50, 50))
self.add_img = ImageTk.PhotoImage(self.add_img)
self.widgets()
self.root.mainloop()
def widgets(self):
self.playlists_tab.place(height=self.height, width=self.width, x=0, y=0)
self.main.add(self.playlists_tab, text="Playlists")
self.main.pack(expand=1, fill="both")
self.playlist_frame = tk.Frame(self.playlists_canvas, bg=self.c)
self.playlists_canvas.create_window((0, 0), window=self.playlist_frame, anchor='center')
self.playlists_canvas.config(bg=self.c)
self.playlists_canvas.place(height=int(self.height / 1.428), width=self.width, x=0, y=int(self.height / 9))
self.add_playlists_button = tk.Button(self.playlists_canvas, image=self.add_img, bg=self.c, bd=0,
command=self.add_playlists)
self.add_playlists_button.place(x=1284, y=75)
self.playlists_scrollbar.pack(side='right', fill='y')
self.playlists_canvas.config(yscrollcommand=self.playlists_scrollbar.set)
self.playlists_canvas.bind('<Configure>', lambda e: self.playlists_canvas.configure(
scrollregion=self.playlists_canvas.bbox('all')))
if os.path.getsize('playlistsnames.txt') != 0:
lines = open('playlistsnames.txt', 'r', encoding='utf-8').read().splitlines()
for i in lines:
self.playlists[i] = []
self.create_playlists()
def create_playlists(self):
self.playlists_buttons_list = []
for i in range(len(self.playlists.keys())):
self.playlists_buttons_list.append(tk.Button(self.playlist_frame, bg=self.c,
text=' ' + list(self.playlists.keys())[i].split('!')[0],
fg='white', image=self.default_img, height=280, width=300))
row = 0
column = 0
for i in self.playlists_buttons_list:
if column > 3:
row += 1
column = 0
if column > 7:
row += 1
column = 0
i.grid(row=row, column=column)
column += 1
def get_name(self):
self.name_of_plst = self.plst_entry.get()
self.playlists[self.name_of_plst] = []
self.create_playlists()
with open('playlistsnames.txt', 'a', encoding='utf-8') as names_file:
names_file.write(self.name_of_plst + '!\n')
def add_playlists(self):
self.add_playlist_win = tk.Toplevel(self.root)
self.name_label = tk.Label(self.add_playlist_win, text='Name:', bg=self.c, fg='pink').pack()
self.plst_entry = tk.Entry(self.add_playlist_win)
self.plst_entry.pack()
self.confirm_btn = tk.Button(self.add_playlist_win, text='Confirm', bg=self.c, fg='pink',
command=self.get_name).pack()
self.add_playlist_win.mainloop()
MyApp()
I should also mention that because I store the playlist names in a file called playlistnames.txt when I rerun the program I can see all the playlist buttons plus the one I created before and things work just fine.
So what I want is making the grid update and work while running the app without having to rerun the app of course
My playlistsnames.txt file has this format:
rock!
metal!
chill!
rap!
jazz!
blues!
hard rock!
trap!
Any suggestions would be helpful!
Thanks in advance!

save entry values for next programmstart tkinter

thanks a lot for your time. I'm currently stuck at the following point: I have developed a GUI with Tkinter with about 200 entries. (For simplification I have only included a small section below). But these 200 entries are seldom filled in at once. Normally 50 entries are filled in every start of the program. When the program is closed, these filled in values are deleted and have to be filled in again after the program is started again. Is there a way to prevent this?
I do not want to lose the values entered in jobNameA_entry and jobNameB_entry when closing the program.
Many thanks in any case.
import tkinter as tk
class Win1:
def __init__(self, master):
self.master = master
self.master.title("Gap Assessment")
self.topFrame = tk.Frame(self.master)
self.topFrame.grid(row=0, column=0, sticky='news', ipady = 5)
self.A_GapFrame = tk.Frame(self.master)
self.B_GapFrame = tk.Frame(self.master)
self.subframe_AGap()
self.subframe_BGap()
# Create a Tkinter variable
self.gapType = tk.StringVar(self.master)
# Dictionary with optionsverschwinden
self.choiceGap = ['AFrame','BFrame']
# self.choiceGap = sorted(self.choiceGap)
self.gapType.set('') # set the default option
self.ctngMenu = tk.OptionMenu(self.topFrame, self.gapType, *self.choiceGap, command=self.chioseGap_handle)
self.ctngMenu.grid(row = 1, column =2)
def chioseGap_handle(self, selected):
if selected == 'AFrame':
self.A_GapFrame.tkraise()
# self.subframe_AGap()
self.A_GapFrame.place(x=20, y=30, width = 210)
self.B_GapFrame.place_forget()
if selected == 'BFrame':
self.B_GapFrame.tkraise()
# self.subframe_BGap()
self.B_GapFrame.place(x=30, y=70, width = 210)
self.A_GapFrame.place_forget()
def subframe_AGap(self):
self.jobNameA_text = tk.StringVar()
self.jobNameA_entry = tk.Entry(self.A_GapFrame, textvariable = self.jobNameA_text)
self.jobNameA_entry.grid(row=1, column=0, sticky='news')
self.jobNameA_text = tk.StringVar()
self.jobNameA_entry = tk.Entry(self.A_GapFrame, textvariable = self.jobNameA_text)
def subframe_BGap(self):
self.jobNameB_text = tk.StringVar()
self.jobNameB_entry = tk.Entry(self.B_GapFrame, textvariable = self.jobNameB_text)
self.jobNameB_entry.grid(row=2, column=0, sticky='news')
self.jobNameB_text = tk.StringVar()
self.jobNameB_entry = tk.Entry(self.B_GapFrame, textvariable = self.jobNameB_text)
root = tk.Tk()
root.geometry("200x300+50+50")
app = Win1(root)
root.mainloop()

How do I align rows of two frames in tkinter?

I have two frames in tkinter. One of them has labels, while the other has text fields and buttons. When a user clicks a button, more fields get added horizontally in the second frame. Both frames are connected to one vertical scrollbar, and the second frame has its own horizontal scrollbar. How can I make it so the first row of the first frame is aligned with the first row of the second frame?
I would like the fields to be aligned with A, B, C labels
from tkinter import *
import pyodbc # Importing for storing in a DB
from tkinter import messagebox
import getpass
import os
from datetime import datetime
from tkinter import ttk
import win32com.client
import openpyxl
from openpyxl import load_workbook
from tkcalendar import Calendar, DateEntry
global totalItems
global itemNum
global sizeList
global typeList
global qtyList
global actualQtyList
actualQtyList=[]
itemNum=0
def myfunction(event):
#canvas.configure(scrollregion=canvas.bbox("all"),height=650)
canvas.configure(scrollregion=canvas.bbox("all"), height=630)
def myfunction2(event):
canvasForCustomers.configure(scrollregion=canvasForCustomers.bbox("all"),height=645,width=900)
def multiple_yview(*args):
canvas.yview(*args)
canvasForCustomers.yview(*args)
def addNewCustomer():
global totalItems
global itemNum
padxValue=0
lbFrame_Customer=ttk.LabelFrame(frameForOfferCreationFilter,text="Customer")
cb_customer=ttk.Combobox(lbFrame_Customer,state='readonly',values=customerList,width=6)
cb_customer.grid(row=0,column=0)
lbFrame_ShipDate=ttk.LabelFrame(frameForOfferCreationFilter,text="Ship Date")
cal_ShipDate=DateEntry(lbFrame_ShipDate)
cal_ShipDate.grid(row=0,column=0)
lbFrame_PackedDateRange=ttk.LabelFrame(frameForOfferCreationFilter,text="Packed Date Range")
cal_FromDate=DateEntry(lbFrame_PackedDateRange)
lb_hyphen=ttk.Label(lbFrame_PackedDateRange,text="-")
cal_ToDate = DateEntry(lbFrame_PackedDateRange)
cal_FromDate.grid(row=0,column=0)
lb_hyphen.grid(row=0,column=1)
cal_ToDate.grid(row=0,column=2)
lbFrame_Customer.grid(row=0,column=itemNum,columnspan=1,padx=padxValue)
lbFrame_ShipDate.grid(row=0,column=itemNum+1,columnspan=1,padx=padxValue)
lbFrame_PackedDateRange.grid(row=0,column=itemNum+2,columnspan=2,padx=padxValue)
lb_CaseSize = ttk.Label(frameForOfferCreationFilter, text="Case Size", justify="center").grid(row=1, column=itemNum,padx=padxValue)
if itemNum%2!=0:
padxValue=20
else:
padxValue=0
indexNum=0
if indexNum%2==0:
padyValue2=0
else:
padyValue2=5
# frameForOfferCreation=Frame(canvasForCustomers,bg='yellow')
# frameForOfferCreation.grid(row=2,column=0,columnspan=6)
for indexNum in range(totalItems):
txt_CaseSize = ttk.Entry(frameForOfferCreationItems, width=7)
txt_CaseSize.grid(row=indexNum, column=itemNum, padx=10+padxValue,pady=padyValue2,sticky=S)
if indexNum % 2 == 0:
padyValue2 = 4
else:
padyValue2 = 0
itemNum = itemNum + 7
root_1 = Tk()
w, h = root_1.winfo_screenwidth(), root_1.winfo_screenheight()
root_1.geometry("%dx%d+0+0" % (w, h))
root_1.title("Sales Allocation Application")
allItems=['A','B','C']
############################ Getting Customers
allCustomers=['X','Y','Z']
customerList=[]
for item in allCustomers:
customerList.append(item[0])
tab_parent = ttk.Notebook(root_1)
tab_parent.pack(expand=1, fill='both')
tab_OfferPage = ttk.Frame(tab_parent)
tab_EditPage=ttk.Frame(tab_parent)
# tab_AllOffers = ttk.Frame(tab_parent)
tab_parent.add(tab_OfferPage, text='Create New Offer')
tab_parent.add(tab_EditPage,text="Edit Existing Offers")
lbFrm_ExistingItems=ttk.LabelFrame(tab_OfferPage,text="Items")
lbFrm_ExistingItems.pack(expand=1,fill='both')
canvas = Canvas(lbFrm_ExistingItems,width=300,height=650) # ,bg="#F4F3F1") width 400
canvas.grid(row=0, column=0,sticky=N)
frameOfItems = Frame(canvas,bg='green')
scrollBar = ttk.Scrollbar(lbFrm_ExistingItems, orient="vertical", command=multiple_yview) # canvas.yview)
canvas.configure(yscrollcommand=scrollBar.set)
frameOfItems.bind("<Configure>", myfunction)
scrollBar.grid(row=0, column=0, sticky=N + S + W) # , sticky=N + S + W)
canvas.create_window((0, 0), window=frameOfItems, anchor='nw')
canvasForCustomers=Canvas(lbFrm_ExistingItems,bg="red",width=900)
canvasForCustomers.grid(row=0, column=1,sticky=N+S)
frameForOfferCreationItems=Frame(canvasForCustomers,bg='pink')
frameForOfferCreationItems.bind("<Configure>", myfunction2)
frameForOfferCreationFilter=Frame(canvasForCustomers,bg='yellow')
frameForOfferCreationFilter.bind("<Configure>", myfunction2)
canvasForCustomers.create_window((0,0),window=frameForOfferCreationFilter,anchor='nw')
canvasForCustomers.create_window((0,80),window=frameForOfferCreationItems,anchor='nw')
btn_addCustomer=ttk.Button(lbFrm_ExistingItems,text="Add\nCustomer",command=addNewCustomer).grid(row=0,column=2,sticky=N+E)
btn_loadExisting=ttk.Button(lbFrm_ExistingItems,text="Load Existing\nOpen Offers").grid(row=0,column=3,sticky=N+E)
totalItems=len(allItems)
scrollBarHorizontal = ttk.Scrollbar(lbFrm_ExistingItems, orient="horizontal", command=canvasForCustomers.xview)
canvasForCustomers.configure(xscrollcommand=scrollBarHorizontal.set)
scrollBarHorizontal.grid(row=1, column=1, sticky=E + W+S)
canvasForCustomers.configure(yscrollcommand=scrollBar.set)
qtyList=[]
for item in allItems:
qtyList.append(Label(frameOfItems,text=item[0]))
actualQtyList.append(item[0])
lb_Qty=ttk.Label(frameOfItems,text="Quantity").grid(row=0,column=1,pady=10)
lb_LineBreak=ttk.Label(frameOfItems,text=" ").grid(row=1,column=0,columnspan=4,pady=12)
##### Adding blank label to attempt alignement
rowNum=2
padyValue=7
for item in range(len(qtyList)):
qtyList[item].grid(row=rowNum,column=4,pady=padyValue)
rowNum=rowNum+1
if rowNum%2==0:
padyValue=7
else:
padyValue=0
root_1.mainloop()
Tkinter is a pretty low-level GUI framework. I'd suggest one of the libraries from here, as they will make your life a whole lot easier.

Tkinter dynamic scrollbar depending on number of entries

I am trying to create a little GUI that takes a various number of inputs from entries. The number of entries should be flexible between zero and 32, and the user can add entries via a button (simplified version of the program).
The problem is that with 32 entries die GUI gets quite long and I'd like to add a scrollbar so to minimize the size of the GUI window and the user can scroll through the entries.
I have developed an example based on code I found on this website but I cannot get the scrollbar to work.
I simplified version of my code is below.
Thanks for your help!
from tkinter import *
class SlowCH_Manager(Canvas):
"""
Manages a variable number of slow channel massages
"""
def __init__(self,master=None,**kwargs):
Canvas.__init__(self,master,**kwargs)
self.frame = Frame(self)
self.create_window(0,0,anchor=N+W,window=self.frame)
self.row = 0
self.widgets = []
self.max = 32
self._init_entries()
def _init_entries(self):
"""
initialize the input area with labels and perhaps default values
"""
label_id = Label(self.frame, text='message ID').grid(row = self.row, column = 1)
label_msg = Label(self.frame, text='message data').grid(row = self.row, column = 2)
self.row += 1
def add_entry(self):
"""
Dynamically add entry to GUI until max number of entries is arrived.
By SENT specification max 32 slow channel messages are allowed.
"""
if len(self.widgets) >= self.max:
print('Im full')
else:
label = Label(self.frame, text=str(len(self.widgets))).grid(row = self.row, column = 0)
entry_id = Entry(self.frame)
entry_id.grid(row = self.row, column = 1)
entry_data = Entry(self.frame)
entry_data.grid(row = self.row, column = 2)
self.row += 1
self.widgets.append(entry_id)
def _ypos(self):
return sum(x.winfo_reqheight() for x in self.widgets)
if __name__ == "__main__":
root = Tk()
manager = SlowCH_Manager(root)
manager.grid(row=0,column=0)
scroll = Scrollbar(root)
scroll.grid(row=0,column=1,sticky=N+S)
manager.config(yscrollcommand = scroll.set)
scroll.config(command=manager.yview)
manager.configure(scrollregion = manager.bbox("all"))
b = Button(root, text = "add entry", command = manager.add_entry)
b.grid(row=1,column=0)
root.mainloop()
You need to update the scrollregion of the canvas each time you add an entry:
if __name__ == "__main__":
root = Tk()
manager = SlowCH_Manager(root)
manager.grid(row=0,column=0)
scroll = Scrollbar(root)
scroll.grid(row=0,column=1,sticky=N+S)
manager.config(yscrollcommand = scroll.set)
scroll.config(command=manager.yview)
manager.configure(scrollregion = manager.bbox("all"))
def command():
manager.add_entry()
# update scrollregion
manager.configure(scrollregion = manager.bbox("all"))
b = Button(root, text = "add entry", command = command)
b.grid(row=1,column=0)
root.mainloop()

Categories