【问题标题】:Scrollbar in Tkinter grid [duplicate]Tkinter网格中的滚动条[重复]
【发布时间】:2012-11-08 14:28:40
【问题描述】:

可能重复:
Adding a scrollbar to a grid of widgets in Tkinter

在我的项目中,我想在一个窗口中显示我的结果,使用 Tkinter 作为 GUI。我使用网格小部件将它们放在一种表格中,并且窗口分为两个不同的部分(用于不同的结果)。但是经过较长时间的运行,显示的结果数量超过了我的屏幕高度,所以我想在我的程序中添加一个滚动条。我已经在 stackoverflow 上查看了几个问题,最接近的答案是:

Adding a scrollbar to a group of widgets in Tkinter (只是为了让你知道我在寻找什么!)

但我无法将其应用到我的程序中,可能是因为我对 Python 比较陌生,有时认为我是一个有教程示例的弗兰肯斯坦博士。

我现在尝试了很多,但我无法让表格显示在画布中,可能只是我缺少一些小东西。

我为我的程序创建了一个抽象示例(没有滚动条),所以您知道我在使用什么,也许您中的某个人可以帮助我将滚动条放在它所属的位置!

非常感谢!

示例代码:(运行)

import Tkinter as tk
toprow=1
botrow=1
class ProgramWindow(tk.Frame): 

    def __init__(self,name): 
        self.name = name
        tk.Frame.__init__(self,root)
        self.pack()

        if name=="BotWin":
            tk.Label(self,text="FirstColBot",width=30).grid(row=0,column=0)            
            tk.Label(self,text="SecndColBot",width=20).grid(row=0,column=1)

        elif name=="TopWin":
            tk.Label(self,text="FirstColTop",width=30).grid(row=0,column=0)         
            tk.Label(self,text="SecndColTop",width=20).grid(row=0,column=1)

    def addrowTop(self,stuff,otherstuff):
        global toprow

        textfield = tk.Text(self,width=30,height=1)
        textfield.grid(row=toprow,column=0)
        textfield.insert('0.0',stuff)

        textfield = tk.Text(self,width=20,height=1)
        textfield.grid(row=toprow,column=1)
        textfield.insert('0.0',otherstuff)

        toprow+=1

    def addrowBot(self,stuff,otherstuff):
        global botrow

        textfield = tk.Text(self,width=30,height=1)
        textfield.grid(row=botrow,column=0)
        textfield.insert('0.0',stuff)

        textfield = tk.Text(self,width=20,height=1)
        textfield.grid(row=botrow,column=1)
        textfield.insert('0.0',otherstuff)

        botrow+=1

def SomeProg():
    for i in range(20):
        if i%2==0:
            stuff = "Stuff is "+str(i)
            otherstuff=i*3
            Wins[0].addrowTop(stuff,otherstuff)
        elif i%2==1:
            stuff = "Stuff is "+str(i)
            otherstuff=i*4
            Wins[1].addrowBot(stuff,otherstuff)


root = tk.Tk()
root.title("Stuff")

Wins = [ ProgramWindow("TopWin"),ProgramWindow("BotWin")]
SomeProg()

root.mainloop()

我尝试添加滚动条的附加代码(基于上面链接中显示的示例)。 如果滚动条只显示在下部,那也没关系,因为那是结果很多的部分。)

import Tkinter as tk
toprow=1
botrow=1
class ProgramWindow(tk.Frame): 

    def __init__(self,name): 
        self.name = name
        self.frame=tk.Frame.__init__(self,root)


        if name=="BotWin":
            tk.Label(self,text="FirstColBot",width=30).grid(row=0,column=0)            
            tk.Label(self,text="SecndColBot",width=20).grid(row=0,column=1)

            self.canvas = tk.Canvas(root, borderwidth=0, background="#ffffff")
            self.vsb = tk.Scrollbar(root, orient="vertical", command=self.canvas.yview)
            self.canvas.configure(yscrollcommand=self.vsb.set)

            self.vsb.pack(side="right", fill="y")
            self.canvas.pack(side="left", fill="both", expand=True)
            self.canvas.create_window((4,4), window=self.frame)

            self.bind("<Configure>", self.OnFrameConfigure)

        elif name=="TopWin":
            self.pack()
            tk.Label(self,text="FirstColTop",width=30).grid(row=0,column=0)         
            tk.Label(self,text="SecndColTop",width=20).grid(row=0,column=1)

    def addrowTop(self,stuff,otherstuff):
        global toprow

        textfield = tk.Text(self,width=30,height=1)
        textfield.grid(row=toprow,column=0)
        textfield.insert('0.0',stuff)

        textfield = tk.Text(self,width=20,height=1)
        textfield.grid(row=toprow,column=1)
        textfield.insert('0.0',otherstuff)

        toprow+=1

    def OnFrameConfigure(self, event):
        self.canvas.configure(scrollregion=self.frame.bbox("all"))

    def addrowBot(self,stuff,otherstuff):
        global botrow

        textfield = tk.Text(self,width=30,height=1)
        textfield.grid(row=botrow,column=0)
        textfield.insert('0.0',stuff)

        textfield = tk.Text(self,width=20,height=1)
        textfield.grid(row=botrow,column=1)
        textfield.insert('0.0',otherstuff)

        botrow+=1

def SomeProg():
    for i in range(20):
        if i%2==0:
            stuff = "Stuff is "+str(i)
            otherstuff=i*3
            Wins[0].addrowTop(stuff,otherstuff)
        elif i%2==1:
            stuff = "Stuff is "+str(i)
            otherstuff=i*4
            Wins[1].addrowBot(stuff,otherstuff)


root = tk.Tk()
root.title("Stuff")

Wins = [ ProgramWindow("TopWin"),ProgramWindow("BotWin")]
SomeProg()

root.mainloop()

【问题讨论】:

  • 没有什么可以添加到您链接的问题中提供的精彩答案和示例中。使用 Brian Oakley 的代码并在所谓的 populate 方法中创建您的项目(或将 ProgramWindows 的父级设置为嵌入框架)。如果您向我们展示您卡在哪里/失败的地方比什么有效,您可能会得到更好的反馈......
  • 我将使用滚动条编辑/添加代码,但它没有显示我想要的内容
  • 我提到了它,应用了它,但它对我不起作用,我不知道为什么。
  • Brian Oakley 示例与您的示例之间的区别是:您的 ProgramWindow 框架没有画布作为父级,OnFrameConfigure 使用self.frame 滚动区域而不是self.canvas
  • 我想要画布的底部,上部可以是正常的部分。当您运行第二个代码时,您会看到在下部有一个画布窗口,我想当我必须将框架分配给画布(这就是为什么它是白色的)和滚动区域(这就是为什么滚动条不可滚动)。我很难改变那个:/

标签: python grid tkinter scrollbar


【解决方案1】:

使Bryan Oakley's answer 适应您的具体问题:

  • 以画布为父级创建框架
  • 使用画布作为scrollregion的参数

注意:在python中进行子类化时,不需要存储父__init__的结果,因为它是对自身进行操作的。

这是补丁:

     def __init__(self,name): 
         self.name = name
-        self.frame=tk.Frame.__init__(self,root)

         if name=="BotWin":
+            self.canvas = tk.Canvas(root, borderwidth=0, background="#ffffff")
+            tk.Frame.__init__(self,self.canvas)
             tk.Label(self,text="FirstColBot",width=30).grid(row=0,column=0)            
             tk.Label(self,text="SecndColBot",width=20).grid(row=0,column=1)
-            self.canvas = tk.Canvas(root, borderwidth=0, background="#ffffff")
             self.vsb = tk.Scrollbar(root, orient="vertical", command=self.canvas.yview)
             self.canvas.configure(yscrollcommand=self.vsb.set)

             self.vsb.pack(side="right", fill="y")
             self.canvas.pack(side="left", fill="both", expand=True)
-            self.canvas.create_window((4,4), window=self.frame)
+            self.canvas.create_window((4,4), window=self)
             self.bind("<Configure>", self.OnFrameConfigure)

         elif name=="TopWin":
+            self.frame=tk.Frame.__init__(self,root)
             self.pack()
             tk.Label(self,text="FirstColTop",width=30).grid(row=0,column=0)         
             tk.Label(self,text="SecndColTop",width=20).grid(row=0,column=1)
@@ -41,7 +40,7 @@
         toprow+=1

     def OnFrameConfigure(self, event):
-        self.canvas.configure(scrollregion=self.frame.bbox("all"))
+        self.canvas.configure(scrollregion=self.canvas.bbox("all"))

     def addrowBot(self,stuff,otherstuff):
         global botrow

【讨论】:

  • 非常感谢!我一直在尝试,我的最后一个结果看起来与你的非常相似,但我没有想到在 OnFrameConfigure() 中将“框架”与“画布”交换,而 create_window 行是我尝试存储的唯一原因它,否则我将没有 self.frame(我拼命地试图以某种方式构建)谢谢你的修复!
【解决方案2】:

从你的问题我很确定我可以帮助你,几个月前我遇到了类似的问题,我尝试了很多不同的解决方案,最后我从 ttk 模块中找到了关于 ttk 树视图小部件的信息,这是python 2.7的标准配置

这里有一个小例子可以帮助你理解我的意思

from Tkinter import *
import ttk
root = Tk()
treedata = [('column 1', 'column 2'), ('column 1', 'column 2')]
column_names = ("heading1", "heading2")
tree = ttk.Treeview(root, columns = column_names, yscrollcommand = scrollbar.set)
scrollbar = ttk.Scrollbar(root)
scrollbar.pack(side = 'right', fill= Y)
for x in treedata:
    tree.insert('', 'end', values =x)
for col in column_names: 
    tree.heading(col, text = col.Title())
scrollbar.config(command=tree.yview)
tree.pack()

希望这会有所帮助,这方面的文档不多,但谷歌会提供帮助, 一个非常有用的链接:http://www.tkdocs.com/tutorial/tree.html

祝你好运:)

【讨论】:

  • 这是一个有趣的选择,但不幸的是,这不适合我的问题,因为我只有两个“组”(我不知道一个合适的词,我不太擅长英语),其中一个tham 包含太多“子条目”,将它们拆分对我来说是没有选择的。我正在考虑将它们分成几个部分(一旦超过 20 行),但这对我来说并不好。但是感谢您的建议,这将是选项卡的不错选择!
  • 当然你可以使用一个while循环来检查它是否少于20行,然后如果超过20运行一个函数来创建一个新的树视图?如果你每个只放 20 个,你为什么需要滚动?您是要单独滚动还是单独滚动?
  • 我不需要使用树形视图滚动,但是在 X 行之后拆分结果对我来说不是选项。如果是的话,树视图将是要走的路;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-25
相关资源
最近更新 更多