TKinter i scroll

0

Cześć,
mam widok w zasadzie identyczny z tym:
http://www.java2s.com/Code/Python/GUI-Tk/2dtableofinputfields.htm

z małą zmianą, że wyliczam długość tekstu w kontrolkach (kontrolki są readonly, a zawartość jest znana przy budowaniu okna) i szerokość wszystkich kontrolek w kolumnie ustawiam na szerokość najdłuższej z nich (tak by każda pomieściła tekst). Zatem w zależności od danych tabela może mieć szerokość od 1000 po 1500 (załóżmy).

Jako, że liczba wierszy jest nieznana i może być duża chciałem zrobić scrolla. Zrobiłem to tym kodem:

def myfunction(event):
    canvas.configure(scrollregion=canvas.bbox("all"),width=1400,height=700)

tk.Entry(root).grid(sticky='we')
root.grid_columnconfigure(0, weight=1)
 
myframe=tk.Frame(root,relief=tk.GROOVE,width=600,height=400,bd=1)
myframe.place(x=0,y=0)

canvas=tk.Canvas(myframe)
frame=tk.Frame(canvas)
myscrollbar=tk.Scrollbar(myframe,orient="vertical",command=canvas.yview)
myscrollbar.pack(side="right",fill="y")
canvas.pack(side="left")
canvas.create_window((0,0),window=frame,anchor='nw')
frame.bind("<Configure>",myfunction)

zmieniając następnie też

e = Entry(frame, borderwidth=0, relief=RIDGE, width=maxWidths[j])

Jedyny problem jak sprawić, żeby:

  • szerokość canvasa na starcie była zawsze równa sumarycznej szerokości kontrolek entry w wierszu
  • szerokość okna była też tyle równa + 23px dla suwaka
  • wysokość canvasa niech będzie na sztywne ustawiona na to 700 załóżmy
  • przy zmianie rozmiaru okna zmieniała się szerokość canvasa oraz proporcjonalnie szerokość wszystkich kontrolek entry
  • przycisk był pod tą tabelą (canvasem)

z przyciskiem próbowałem zrobić tak, że w metodzie grid ustawiałem row=ilośćWierszyKontrolekEntry+1, ale przycisk się nie pojawiał. Bez tego zaś jest on na środku okna.
Potrafię to wszystko wyliczyć i wstawić na sztywno, ale nie będzie reagować na zmianę rozmiaru okna, a pewnie da się ro zrobić jakoś bardziej autaomatycznie. Ustawienie zaś "pack" zamiast "grid" przy przycisku zawiesza uruchamiającą się aplikację.

Pełny przykładowy kod:

import tkinter as tk

class Data:
    def __init__(self,name,team,ident,date,details):
        self.dictionary = {"NAME": name, 'TEAM': team, "IDENTIFIER": ident, "DATE": date, "DETAILS": details}
    def getValueForKey(self,key):
        return self.dictionary[key]

headers = ["Name", "Team", "Identifier", "Date", "Details"]
maxWidths = [0,0,0,0,0]
mainList = [Data("a","b","c","d","e"),Data("aa","bb","cc","dd","ee"),Data("aaa","bbb","ccc","ddd","eee"),Data("aaaa","bbbb","cccc","dddd","eeee"),
            Data("aaaaa", "bbbbb", "ccccc", "ddddd", "eeeee"), Data("aaaaaa","bbbbbb","cccccc","dddddd","eeeeee"),
            Data("a","fshaewyaew hfadfhos dfs hsiousdadfsiu ", "c", "d","ewfhsauhfdsu hsdfo iadhsdfos iadfoshadfs oai huadfs adfhsdfsaasdfo aho ")]

for element in mainList:
    for i in range(len(headers)):
        lengthOfElement = len(element.getValueForKey(headers[i].upper()))
        if maxWidths[i] < lengthOfElement:
            maxWidths[i] = lengthOfElement
        if maxWidths[i] > 50:
            maxWidths[i] = 50

root = tk.Tk()
root.geometry("1423x700")

def myfunction(event):
    canvas.configure(scrollregion=canvas.bbox("all"),width=1400,height=500)

tk.Entry(root).grid(sticky='we')
root.grid_columnconfigure(0, weight=1)

myframe=tk.Frame(root,relief=tk.GROOVE,width=600,height=400,bd=1)
myframe.place(x=0,y=0)

canvas=tk.Canvas(myframe)
frame=tk.Frame(canvas)
myscrollbar=tk.Scrollbar(myframe,orient="vertical",command=canvas.yview)
myscrollbar.pack(side="right",fill="y")
canvas.pack(side="left")
canvas.create_window((0,0),window=frame,anchor='nw')
frame.bind("<Configure>",myfunction)

def callback(event):
    print(event.widget.grid_info()["row"])

rows = []
for i in range(len(mainList)+1):
    cols = []
    for j in range(len(headers)):
        if i == 0:
            control = tk.Label(frame, text=headers[j])
            control.grid(row = i, column = j)
        else:
            control = tk.Entry(frame, borderwidth=0, relief=tk.RIDGE, width=maxWidths[j]+1)
            control.grid(row=i, column=j, sticky=tk.NSEW)
            control.insert(tk.END, mainList[i-1].getValueForKey(headers[j].upper()))
            control.bind("<Button-1>",callback)
            control.config(state="readonly")
        cols.append(control)
    rows.append(cols)

def onPress():
    print("something")

tk.Button(text='Get details', command=onPress).grid()
tk.mainloop()
0

W sumie odpowiedź jest prosta. Matematyka ci pomoże. I aktualizacja zmiennej, czyli musisz sobie znaleźć przykładową funkcję "update" wykonującą się co jakiś czas w tkinterze.

1 użytkowników online, w tym zalogowanych: 0, gości: 1