使用Tkinter(Python)向框架添加滚动条

时间:2013-10-08 11:00:45

标签: python user-interface tkinter

我有一个简单的GUI,在显示要显示的初始选项的数量后,向用户显示一些选项。在这种情况下,4:

initial

通过单击Add row,您可以向GUI添加一行。问题是,如果用户想要100个选项,则GUI变得特别大,并且不显示所有选项。 big

所以我想只在选项空间上有一个滚动条,而不是其余部分。对不起的Photoshop很抱歉,但我希望有这样的东西: desiredsolution

选项空间是FrameTwo,因此我希望将整个FrameTwo放在滚动条内,如上图所示。

# -*- coding: utf-8 -*-
from Tkinter import *
import Image
import ImageTk
import tkFileDialog
import datetime

class Planificador(Frame):
    def __init__(self,master):
        Frame.__init__(self, master)
        self.master = master
        self.initUI()

    def initUI(self):
        self.master.title("Plan")
        self.frameOne = Frame(self.master)
        self.frameOne.grid(row=0,column=0)
        self.frameTwo = Frame(self.master)
        self.frameTwo.grid(row=1, column=0)
        self.frameThree = Frame(self.master)
        self.frameThree.grid(row=2, column=0)

        # Borrar esto?
        self.txt = Text(self)
        self.txt.pack(fill=BOTH, expand=1)

        self.piezastext = Label(self.frameOne, text = " Amount of pieces ", justify="center")
        self.piezastext.grid(row=1, column=0)
        self.entrypiezas = Entry(self.frameOne,width=3)
        self.entrypiezas.grid(row=2, column=0, pady=(5,5))
        self.aceptarnumpiezas = Button(self.frameOne,text="Click me", command=self.aceptar_piezas,width=8)
        self.aceptarnumpiezas.grid(row=6, column=0, pady=(5,5))

    def aceptar_piezas(self):
        try:
            val = int(self.entrypiezas.get())
            self.aceptar_piezas_ok()
        except ValueError:
            showerror('Error', "Introduce un numero")

    def aceptar_piezas_ok(self):
        self.num_piezas = self.entrypiezas.get()

        self.piezastext.grid_remove()
        self.entrypiezas.grid_remove()
        self.aceptarnumpiezas.grid_remove()

        self.optionmenus_piezas = list()
        self.numpiezas = []
        self.numerolotes = []
        self.optionmenus_prioridad = list()
        self.lotes = list()

        self.mispiezas = ['One', 'Two', 'Three', 'Four', 'Five']

        self.n = 1
        while self.n <= int(self.num_piezas):
            self.textopieza = Label(self.frameTwo, text = "Pieza: ", justify="left")
            self.textopieza.grid(row=self.n, column=0)

            var = StringVar()
            menu = OptionMenu(self.frameTwo, var, *self.mispiezas)
            menu.config(width=10)
            menu.grid(row=self.n, column=1)
            var.set("One")
            self.optionmenus_piezas.append((menu, var))

            self.numpiezastext = Label(self.frameTwo, text = "Numero de piezas: ", justify="center")
            self.numpiezastext.grid(row=self.n, column=2, padx=(10,0))
            self.entrynumpiezas = Entry(self.frameTwo,width=6)
            self.entrynumpiezas.grid(row=self.n, column=3, padx=(0,10))
            self.entrynumpiezas.insert(0, "0")

            self.textoprioridad = Label(self.frameTwo, text = "Prioridad: ", justify="center")
            self.textoprioridad.grid(row=self.n, column=4)
            var2 = StringVar()
            menu2 = OptionMenu(self.frameTwo, var2, "Normal", "Baja", "Primera pieza", "Esta semana")
            menu2.config(width=10)
            menu2.grid(row=self.n, column=5)
            var2.set("Normal")
            self.optionmenus_prioridad.append((menu2, var2))

            self.lotestext = Label(self.frameTwo, text = "Por lotes?", justify="center")
            self.lotestext.grid(row=self.n, column=6, padx=(10,0))
            self.var1 = IntVar()
            self.entrynumlotes = Checkbutton(self.frameTwo, variable=self.var1)
            self.entrynumlotes.grid(row=self.n, column=7, padx=(5,10))
            self.lotes.append(self.var1)
            self.numpiezas.append(self.entrynumpiezas)

            self.n += 1

        self.anadirpiezas = Button(self.frameThree, text="Add row", command=self.addpieza, width=10)
        self.anadirpiezas.grid(row=0, column=2, pady=(10,10))

        self.calculotext = Label(self.frameThree, text = "Other stuff ")
        self.calculotext.grid(row=1, column=2, padx=(10,0), pady=(10,10))

        self.graspbutton = Button(self.frameThree, text="OPT 1", width=10)
        self.graspbutton.grid(row=2, column=1)

        self.parettobutton = Button(self.frameThree, text="OPT 2",width=10)
        self.parettobutton.grid(row=2, column=2, pady=(10,10), padx=(10,0))

        self.parettoEvolbutton = Button(self.frameThree, text="OPT 2", width=10)
        self.parettoEvolbutton.grid(row=2, column=3, pady=(10,10), padx=(10,0))


    def addpieza(self):
            self.textopiezanuevo = Label(self.frameTwo, text = "Pieza: ", justify="left")
            self.textopiezanuevo.grid(row=int(self.num_piezas)+1, column=0)

            var = StringVar()
            menu = OptionMenu(self.frameTwo, var, *self.mispiezas)
            menu.grid(row=self.n, column=1)
            menu.config(width=10)
            menu.grid(row=int(self.num_piezas)+1, column=1)
            var.set("One")
            self.optionmenus_piezas.append((menu, var))

            self.numpiezastext = Label(self.frameTwo, text = "Numero de piezas: ", justify="center")
            self.numpiezastext.grid(row=int(self.num_piezas)+1, column=2, padx=(10,0))
            self.entrynumpiezas = Entry(self.frameTwo,width=6)
            self.entrynumpiezas.grid(row=int(self.num_piezas)+1, column=3, padx=(0,10))
            self.entrynumpiezas.insert(0, "0")

            self.textoprioridad = Label(self.frameTwo, text = "Prioridad: ", justify="center")
            self.textoprioridad.grid(row=int(self.num_piezas)+1, column=4)
            var2 = StringVar()
            menu2 = OptionMenu(self.frameTwo, var2, "Normal", "Baja", "Primera pieza", "Esta semana")
            menu2.config(width=10)
            menu2.grid(row=int(self.num_piezas)+1, column=5)
            var2.set("Normal")
            self.optionmenus_prioridad.append((menu2, var2))

            self.lotestext = Label(self.frameTwo, text = "Por lotes?", justify="center")
            self.lotestext.grid(row=int(self.num_piezas)+1, column=6, padx=(10,0))
            self.var1 = IntVar()
            self.entrynumlotes = Checkbutton(self.frameTwo, variable=self.var1)
            self.entrynumlotes.grid(row=int(self.num_piezas)+1, column=7, padx=(5,10))
            self.lotes.append(self.var1)

            self.numpiezas.append(self.entrynumpiezas)
            self.num_piezas = int(self.num_piezas)+1

if __name__ == "__main__":
    root = Tk()
    aplicacion = Planificador(root)
    root.mainloop()

FrameOne用于放置我删除的图像,以使此示例更简单。 FrameThree是您可以在GUI底部看到的按钮。

因此,如果有人可以帮助我并告诉我如何将整个FrameTwo放在滚动条内,如第3张图片所示,那将非常有用。

提前致谢。

2 个答案:

答案 0 :(得分:1)

你的一个问题是,“frameTwo”对它的大小没有限制。如果您不限制它的大小,您添加的任何滚动条都不会动作。但是限制框架的大小会限制你可以网格化的行数,这使得滚动条无法再次使用。

解决方案是在“frameTwo”内创建一个框架,以接收您创建的部分。这样,一方面,允许您限制“frameTwo”的大小并将滚动条附加到它,另一方面,允许您将添加到“frameTwo”内部框架的碎片网格化,命名,让我们说,“ListFrame”。当“ListFrame”大小变得大于“frameTwo”大小时,您现在可以使滚动条工作。

我使用上述更改更改了您的代码。看看这个。 更改在代码中进行了注释。 对不起,简短的解释,但我有点匆忙。我有更多时间可以编辑这个答案。

PS:对不起,如果我的英语不是最好的

# -*- coding: utf-8 -*-
from Tkinter import *
import Image
import ImageTk
import tkFileDialog
import datetime

class Planificador(Frame):
    def __init__(self,master):
        Frame.__init__(self, master)
        self.master = master
        self.initUI()

    def initUI(self):
        self.master.title("Plan")
        self.frameOne = Frame(self.master)
        self.frameOne.grid(row=0,column=0)

        self.frameTwo = Frame(self.master)
        self.frameTwo.grid(row=1, column=0)

        #Creating of a new frame, inside of "frameTwo" to the objects to be inserted
        #Creating a scrollbar

        #The reason for this, is to attach the scrollbar to "FrameTwo", and when the size of frame "ListFrame" exceed the size of frameTwo, the scrollbar acts
        self.canvas=Canvas(self.frameTwo)
        self.listFrame=Frame(self.canvas)
        self.scrollb=Scrollbar(self.master, orient="vertical",command=self.canvas.yview)
        self.scrollb.grid(row=1, column=1, sticky='nsew')  #grid scrollbar in master, but
        self.canvas['yscrollcommand'] = self.scrollb.set   #attach scrollbar to frameTwo

        self.canvas.create_window((0,0),window=self.listFrame,anchor='nw')
        self.listFrame.bind("<Configure>", self.AuxscrollFunction)
        self.scrollb.grid_forget()                         #Forget scrollbar because the number of pieces remains undefined by the user. But this not destroy it. It will be "remembered" later.

        self.canvas.pack(side="left")
        self.frameThree = Frame(self.master)
        self.frameThree.grid(row=2, column=0)

        # Borrar esto?
        self.txt = Text(self)
        self.txt.pack(fill=BOTH, expand=1)

        self.piezastext = Label(self.frameOne, text = " Amount of pieces ", justify="center")
        self.piezastext.grid(row=1, column=0)
        self.entrypiezas = Entry(self.frameOne,width=3)
        self.entrypiezas.grid(row=2, column=0, pady=(5,5))
        self.aceptarnumpiezas = Button(self.frameOne,text="Click me", command=self.aceptar_piezas,width=8)
        self.aceptarnumpiezas.grid(row=6, column=0, pady=(5,5))

    def AuxscrollFunction(self,event):
        #You need to set a max size for frameTwo. Otherwise, it will grow as needed, and scrollbar do not act
        self.canvas.configure(scrollregion=self.canvas.bbox("all"),width=600,height=500)

    def aceptar_piezas(self):



        #IMPORTANT!!! All the objects are now created in "ListFrame" and not in "frameTwo"
        #I perform the alterations. Check it out
        try:
            val = int(self.entrypiezas.get())
            self.aceptar_piezas_ok()
            self.scrollb.grid(row=1, column=1, sticky='nsew')  #grid scrollbar in master, because user had defined the numer of pieces
        except ValueError:
            showerror('Error', "Introduce un numero")

    def aceptar_piezas_ok(self):
        self.num_piezas = self.entrypiezas.get()

        self.piezastext.grid_remove()
        self.entrypiezas.grid_remove()
        self.aceptarnumpiezas.grid_remove()

        self.optionmenus_piezas = list()
        self.numpiezas = []
        self.numerolotes = []
        self.optionmenus_prioridad = list()
        self.lotes = list()

        self.mispiezas = ['One', 'Two', 'Three', 'Four', 'Five']

        self.n = 1
        while self.n <= int(self.num_piezas):
            self.textopieza = Label(self.listFrame, text = "Pieza: ", justify="left")
            self.textopieza.grid(row=self.n, column=0)

            var = StringVar()
            menu = OptionMenu(self.listFrame, var, *self.mispiezas)
            menu.config(width=10)
            menu.grid(row=self.n, column=1)
            var.set("One")
            self.optionmenus_piezas.append((menu, var))

            self.numpiezastext = Label(self.listFrame, text = "Numero de piezas: ", justify="center")
            self.numpiezastext.grid(row=self.n, column=2, padx=(10,0))
            self.entrynumpiezas = Entry(self.listFrame,width=6)
            self.entrynumpiezas.grid(row=self.n, column=3, padx=(0,10))
            self.entrynumpiezas.insert(0, "0")

            self.textoprioridad = Label(self.listFrame, text = "Prioridad: ", justify="center")
            self.textoprioridad.grid(row=self.n, column=4)
            var2 = StringVar()
            menu2 = OptionMenu(self.listFrame, var2, "Normal", "Baja", "Primera pieza", "Esta semana")
            menu2.config(width=10)
            menu2.grid(row=self.n, column=5)
            var2.set("Normal")
            self.optionmenus_prioridad.append((menu2, var2))

            self.lotestext = Label(self.listFrame, text = "Por lotes?", justify="center")
            self.lotestext.grid(row=self.n, column=6, padx=(10,0))
            self.var1 = IntVar()
            self.entrynumlotes = Checkbutton(self.listFrame, variable=self.var1)
            self.entrynumlotes.grid(row=self.n, column=7, padx=(5,10))
            self.lotes.append(self.var1)
            self.numpiezas.append(self.entrynumpiezas)

            self.n += 1

        self.anadirpiezas = Button(self.frameThree, text="Add row", command=self.addpieza, width=10)
        self.anadirpiezas.grid(row=0, column=2, pady=(10,10))

        self.calculotext = Label(self.frameThree, text = "Other stuff ")
        self.calculotext.grid(row=1, column=2, padx=(10,0), pady=(10,10))

        self.graspbutton = Button(self.frameThree, text="OPT 1", width=10)
        self.graspbutton.grid(row=2, column=1)

        self.parettobutton = Button(self.frameThree, text="OPT 2",width=10)
        self.parettobutton.grid(row=2, column=2, pady=(10,10), padx=(10,0))

        self.parettoEvolbutton = Button(self.frameThree, text="OPT 2", width=10)
        self.parettoEvolbutton.grid(row=2, column=3, pady=(10,10), padx=(10,0))


    def addpieza(self):
            self.textopiezanuevo = Label(self.listFrame, text = "Pieza: ", justify="left")
            self.textopiezanuevo.grid(row=int(self.num_piezas)+1, column=0)

            var = StringVar()
            menu = OptionMenu(self.listFrame, var, *self.mispiezas)
            menu.grid(row=self.n, column=1)
            menu.config(width=10)
            menu.grid(row=int(self.num_piezas)+1, column=1)
            var.set("One")
            self.optionmenus_piezas.append((menu, var))

            self.numpiezastext = Label(self.listFrame, text = "Numero de piezas: ", justify="center")
            self.numpiezastext.grid(row=int(self.num_piezas)+1, column=2, padx=(10,0))
            self.entrynumpiezas = Entry(self.listFrame,width=6)
            self.entrynumpiezas.grid(row=int(self.num_piezas)+1, column=3, padx=(0,10))
            self.entrynumpiezas.insert(0, "0")

            self.textoprioridad = Label(self.listFrame, text = "Prioridad: ", justify="center")
            self.textoprioridad.grid(row=int(self.num_piezas)+1, column=4)
            var2 = StringVar()
            menu2 = OptionMenu(self.listFrame, var2, "Normal", "Baja", "Primera pieza", "Esta semana")
            menu2.config(width=10)
            menu2.grid(row=int(self.num_piezas)+1, column=5)
            var2.set("Normal")
            self.optionmenus_prioridad.append((menu2, var2))

            self.lotestext = Label(self.listFrame, text = "Por lotes?", justify="center")
            self.lotestext.grid(row=int(self.num_piezas)+1, column=6, padx=(10,0))
            self.var1 = IntVar()
            self.entrynumlotes = Checkbutton(self.listFrame, variable=self.var1)
            self.entrynumlotes.grid(row=int(self.num_piezas)+1, column=7, padx=(5,10))
            self.lotes.append(self.var1)

            self.numpiezas.append(self.entrynumpiezas)
            self.num_piezas = int(self.num_piezas)+1

if __name__ == "__main__":
    root = Tk()
    aplicacion = Planificador(root)
    root.mainloop()

答案 1 :(得分:-4)

您在FrameTwo中有选项菜单,标签,输入框和检查按钮。您如何期望整个框架的滚动条可以工作?它会同时滚动所有小部件吗? Tkinter滚动条通常附加到列表框,画布,条目小部件和文本字段。 http://effbot.org/zone/tkinter-scrollbar-patterns.htm想出一个简单的例子,说明问题需要进一步的帮助。