如何将滚动条添加到包含一组网格按钮的框架中?

2024-06-16 08:23:17 发布

您现在位置:Python中文网/ 问答频道 /正文

所以我编写了一个代码,生成一个窗口,上面有一个按钮,下面有一个小框架。单击顶部的按钮,在下面的小框中的第0列第0行创建了另一个按钮,再次单击它,在第0列第1行创建了另一个按钮,到目前为止一切正常

我现在要做的是添加一个滚动条,这样,如果下面小框架中显示的行都充满了按钮,我可以向下滚动到进一步添加的按钮。因此,一般的问题是:如何将滚动条添加到包含通过grid()组织的已创建按钮的框架中

我已经尝试在一个框架中对创建的按钮进行网格化,并将该框架设置到画布中,然后将滚动条添加到该画布中,但没有任何效果(在下面的代码中,去掉scrollbar小部件的四行,您将看到程序是如何工作的。这四行的添加奇怪地使其他任何东西都消失了)

## 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)

我发现这个选择多亏了ju4321(Tkinter canvas & scrollbar with grid)多亏了这个家伙


Tags: theinfieldfordefcolumnbuttonlabel