Итак, я запрограммировал код, который генерирует окно с кнопкой сверху и маленькой рамкой внизу.Вы нажимаете на кнопку сверху, и в столбце 0 строки 0 в маленькой рамке внизу создается другая кнопка, вы нажимаете на нее еще раз, и в столбце 1 строки 1 создается еще одна кнопка, пока все хорошо, что все работает.
Теперь я хочу добавить полосу прокрутки, чтобы, если строки, отображаемые в небольшом кадре ниже, были заполнены кнопками, я мог прокрутить вниз до кнопок, добавленных ниже.Общий вопрос таков: как я могу добавить полосу прокрутки к фрейму, содержащему созданные кнопки, организованные с помощью grid ()?
Я уже пытался создать сетку созданных кнопок в рамке и установить эту рамку в холст, а затем добавить полосу прокрутки на этот холст, но ничего не получалось.(В приведенном ниже коде выньте четыре строки виджета полосы прокрутки, и вы увидите, как работает программа. Добавление четырех строк странным образом приводит к исчезновению чего-либо еще).
## import required modules ##
from tkinter import *
from functools import partial
## create window ##
window = Tk()
window.geometry("800x800")
## create global frame, which contains a canvas, which in turn contains ##
## the frame containing the grid of the products. This needs to be done ##
## in this way to be able to add a scrollbar aside the products grid ##
Globalframe = Frame(window, height = 210, width = 725)
Globalframe.place(relx = 0.03, rely = 0.54475)
Canv = Canvas(Globalframe, height = 198, width = 712)
Canv.place(relx = 0.00, rely = 0.01)
field = Frame(Canv, height = 186, width = 699)
field.place(relx = 0.00, rely = 0.01)
## add a scrollbar & configure it ##
scroll = Scrollbar(Globalframe, orient = VERTICAL)
scroll.config(command=Canv.yview)
Canv.config(yscrollcommand=scroll.set)
scroll.pack(side=RIGHT, fill=Y)
## create ADD button; function mentioned in command must be defined first ##
# predefine manufacturer variables & lists #
RIGOLVar = IntVar()
DataApexVar = IntVar()
DANIVar = IntVar()
Manufacturers = [["APPLE",RIGOLVar],["BANANA",DataApexVar],["PINEAPPLE",DANIVar]]
# predefine product variables & lists --> Put Lists into respective loops #
# because otherwise the system sends an unknown function error, which is #
# why the lists have been placed below the defined functions in the loop #
L31 = IntVar()
L32 = IntVar()
L34 = IntVar()
ListRIG=[["RED",L31],["GREEN",L32],["BROWN",L34]]
C801 = IntVar()
C82 = IntVar()
ListDAP =[["YELLOW",C801],["BROWN",C82]]
MS = IntVar()
HS = IntVar()
DHS = IntVar()
ListDAN=[["FRESH",MS],["INTERMEDIATE",HS],["OLD",DHS]]
# predefine amount variables & lists & directly sum it all up in one function (always the same) #
ONE = IntVar()
TWO = IntVar()
THREE = IntVar()
FOUR = IntVar()
FIVE = IntVar()
SIX = IntVar()
SEVEN = IntVar()
EIGHT = IntVar()
NINE = IntVar()
TEN = IntVar()
ELEVEN = IntVar()
TWELVE = IntVar()
THIRTEEN = IntVar()
FOURTEEN = IntVar()
FIFTEEN = IntVar()
SIXTEEN = IntVar()
SEVENTEEN = IntVar()
EIGHTEEN = IntVar()
NINETEEN = IntVar()
TWENTY = IntVar()
Varlist = [ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE,TEN,ELEVEN,TWELVE,THIRTEEN,FOURTEEN,FIFTEEN,SIXTEEN,SEVENTEEN,EIGHTEEN,NINETEEN,TWENTY]
Amlist = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
def detamount(Var):
for x in Varlist:
if x == Var:
x.set(1)
else:
x.set(0)
def OPAM(p):
a = StringVar()
for y in Merlist:
if y[1].get() == 1:
a = str(y[0])
else:
pass
for label in field.grid_slaves(row=p,column=6):
label.grid_forget()
mine = Label(field,text =a+"x",bg="cyan")
mine.grid(row=p, column = 6)
def F1(p):
detamount(ONE)
OPAM(p)
def F2(p):
detamount(TWO)
OPAM(p)
def F3(p):
detamount(THREE)
OPAM(p)
def F4(p):
detamount(FOUR)
OPAM(p)
def F5(p):
detamount(FIVE)
OPAM(p)
def F6(p):
detamount(SIX)
OPAM(p)
def F7(p):
detamount(SEVEN)
OPAM(p)
def F8(p):
detamount(EIGHT)
OPAM(p)
def F9(p):
detamount(NINE)
OPAM(p)
def F10(p):
detamount(TEN)
OPAM(p)
def F11(p):
detamount(ELEVEN)
OPAM(p)
def F12(p):
detamount(TWELVE)
OPAM(p)
def F13(p):
detamount(THIRTEEN)
OPAM(p)
def F14(p):
detamount(FOURTEEN)
OPAM(p)
def F15(p):
detamount(FIFTEEN)
OPAM(p)
def F16(p):
detamount(SIXTEEN)
OPAM(p)
def F17(p):
detamount(SEVENTEEN)
OPAM(p)
def F18(p):
detamount(EIGHTEEN)
OPAM(p)
def F19(p):
detamount(NINETEEN)
OPAM(p)
def F20(p):
detamount(TWENTY)
OPAM(p)
Famlist = [F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,F13,F14,F15,F16,F17,F18,F19,F20]
Merlist = []
for i in range(20):
Merlist.append([Amlist[i],Varlist[i],Famlist[i]])
def askamount(p):
ab= Menubutton(field, text="Amount ?")
ab.menu = Menu(ab)
ab["menu"] = ab.menu
for i in Merlist:
ab.menu.add_checkbutton(label=i[0],variable = i[1],command=partial(i[2],p))
ab.grid(row=p, column = 5)
# function - Add Remove button, Manufacturer Label, & product dropdown menu #
# Define function to create product's output (functionalized because always same logic) #
def OPProd(li,co,p):
n = StringVar()
for s in li:
if s[1].get() == 1:
n = str(s[0])
else:
pass
for label in field.grid_slaves(row=r,column=co):
label.grid_forget()
mylab = Label(field,text=n,bg="green")
mylab.grid(row=p,column=co)
# Determine the picked Manufacturer and print the corresponding label to the right #
def setMANVar(V):
for b in Manufacturers:
if b[1] == V:
b[1].set(1)
else:
b[1].set(0)
def OPMAN(p):
c = StringVar()
for d in Manufacturers:
if d[1].get()==1:
c = str(d[0])
else:
pass
# Delete any previously created labels, to have the correct one for the end #
for label in field.grid_slaves(row=p,column=2):
label.grid_forget()
# Create the Label of the correct Manufacturer #
myl = Label(field,text=c,bg="green")
myl.grid(row=p,column=2)
# Create the next general checkbutton for the products #
pb = Menubutton(field,text = "Product ?")
pb.grid(row=p,column=3)
pb.menu = Menu(pb, tearoff=0)
pb["menu"] = pb.menu
# Create the dropdown-list of the product's button just created, in function of the picked manufacturer #
for label in field.grid_slaves(row=p,column=2):
if label["text"]=="APPLE":
def setRIGVar(Var):
for m in ListRIG:
if m[1] == Var:
m[1].set(1)
else:
m[1].set(0)
def FL31(p):
setRIGVar(L31)
OPProd(ListRIG,4,p)
askamount(p)
def FL32(p):
setRIGVar(L32)
OPProd(ListRIG,4,p)
askamount(p)
def FL34(p):
setRIGVar(L34)
OPProd(ListRIG,4,p)
askamount(p)
ListFRIG=[FL31,FL32,FL34]
for i in range(len(ListRIG)):
ListRIG[i].append(ListFRIG[i])
for i in ListRIG:
pb.menu.add_checkbutton(label=i[0],variable=i[1],command=partial(i[2],p))
elif label["text"]=="BANANA":
def setDAPVar(Var):
for m in ListDAP:
if m[1] == Var:
m[1].set(1)
else:
m[1].set(0)
def F801(p):
setDAPVar(C801)
OPProd(ListDAP,4,p)
askamount(p)
def F82(p):
setDAPVar(C82)
OPProd(ListDAP,4,p)
askamount(p)
ListFDAP=[F801,F82]
for i in range(len(ListDAP)):
ListDAP[i].append(ListFDAP[i])
for i in ListDAP:
pb.menu.add_checkbutton(label=i[0],variable=i[1],command=partial(i[2],p))
elif label["text"]=="PINEAPPLE":
def setDANVar(Var):
for m in ListDAN:
if m[1] == Var:
m[1].set(1)
else:
m[1].set(0)
def FMS(p):
setDANVar(MS)
OPProd(ListDAN,4,p)
askamount(p)
def FHS(p):
setDANVar(HS)
OPProd(ListDAN,4,p)
askamount(p)
def FDHS(p):
setDANVar(DHS)
OPProd(ListDAN,4,p)
askamount(p)
ListFDAN = [FMS,FHS,FDHS]
for i in range(len(ListDAN)):
ListDAN[i].append(ListFDAN[i])
for i in ListDAN:
pb.menu.add_checkbutton(label=i[0],variable=i[1],command=partial(i[2],p))
# Manufacturer Functions which set only the picked Manufacturer-Checkbutton = 1 and print the OP - Label #
def FRIG(p):
setMANVar(RIGOLVar)
OPMAN(p)
def FDAP(p):
setMANVar(DataApexVar)
OPMAN(p)
def FDAN(p):
setMANVar(DANIVar)
OPMAN(p)
## Define Clearline Function, associated to the remove button ##
def Clearline(p):
global num
for label in field.grid_slaves(row=p,column=0):
clickedbutton = label
for label in field.grid_slaves(row=p):
label.grid_forget()
remove_button_IDs.remove(clickedbutton)
for button in remove_button_IDs:
button.configure(text="- Remove Product #" + str(remove_button_IDs.index(button)+1))
num -= 1
## Create function associated to the ADD, starting up with the Remove and Manuf Button on a new row ##
r = -1
num = 0
remove_button_IDs = []
def AddProduct():
global r
global num
r += 1
num += 1
button = Button(field,text = "- Remove Product #" + str(num), bg = "red",command = partial(Clearline,r))
button.grid(row=r,column=0)
remove_button_IDs.append(button)
mb = Menubutton(field,text = "What ?")
mb.grid(row=r,column=1)
mb.menu = Menu(mb,tearoff=0)
mb["menu"] = mb.menu
ListFManufacturers = [FRIG,FDAP,FDAN]
for i in range(len(Manufacturers)):
Manufacturers[i].append(ListFManufacturers[i])
for i in Manufacturers:
mb.menu.add_checkbutton(label=i[0],variable=i[1],command= partial(i[2],r))
## Create ADD Button ##
A = Button(window, text = "+ Add a new product",command = AddProduct)
A.place(relx = 0.2, rely = 0.01)
исправление отстрока 15:
def update_scrollregion(event):
Canv.configure(scrollregion=Canv.bbox("all"))
Globalframe = Frame(window, height = 210, width = 725)
Globalframe.place(relx = 0.03, rely = 0.54475)
Canv = Canvas(Globalframe, height = 198, width = 712)
Canv.grid(row=0,column=0,sticky="nsew")
field = Frame(Canv)
Canv.create_window(0,0,window=field,anchor="nw")
## add a scrollbar & configure it ##
s = Scrollbar(Globalframe, orient=VERTICAL)
s.config(command=Canv.yview)
Canv.config(yscrollcommand=s.set)
s.grid(row=0, column=1, sticky="ns")
field.bind("<Configure>",update_scrollregion)
Я нашел эту опцию благодаря j_4321 ( Холст и полоса прокрутки Tkinter с сеткой ). Большое спасибо этому парню!