在Tkinter中向一组小部件添加滚动条

我使用Python解析日志文件中的条目,并使用Tkinter显示条目内容,到目前为止,它非常出色。输出是标签小部件的网格,但有时显示的行数比屏幕上的要多。我想添加一个滚动条,看起来应该很简单,但是我想不出来。

文档意味着只有列表、文本框、画布和条目小部件支持滚动条接口。所有这些似乎都不适合显示小部件网格。在画布小部件中放置任意的小部件是可能的,但是您似乎必须使用绝对的协调,这样我就不能使用网格布局管理器了?

我尝试过将小部件网格放到一个框架中,但这似乎不支持滚动条接口,所以这是行不通的:

mainframe = Frame(root, yscrollcommand=scrollbar.set)

有人能提出解决这个限制的办法吗?我讨厌用PyQt重写,并将我的可执行映像大小增加这么多,只是为了添加一个滚动条!

在Tkinter中向一组小部件添加滚动条

慕后森
浏览 3042回答 2
2回答

慕斯王

概述您只能将滚动条与一些小部件关联起来,根小部件和Frame不是那组小部件的一部分。最常见的解决方案是创建一个画布小部件,并将滚动条与该小部件关联起来。然后,将包含标签小部件的框架嵌入到画布中。确定框架的宽度/高度,并将其输入画布。scrollregion选项,以便滚动区域与框架的大小完全匹配。在画布上直接绘制文本项并不困难,因此如果画布框架内嵌解决方案看起来过于复杂,您可能需要重新考虑这种方法。由于要创建网格,每个文本项的坐标将非常容易计算,特别是如果每一行的高度相同(如果使用单一字体,可能就是这样)。要在画布上直接绘图,只需计算出所使用字体的线条高度(这方面有一些命令)。然后,每个y坐标是row*(lineheight+spacing)..x坐标将是基于每列中最宽项的固定数。如果为列中的所有项都赋予标记,则可以使用单个命令调整列中所有项的x坐标和宽度。面向对象的解决方案下面是一个使用面向对象方法的画布框架内嵌解决方案的示例:import&nbsp;tkinter&nbsp;as&nbsp;tkclass&nbsp;Example(tk.Frame): &nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;__init__(self,&nbsp;root): &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tk.Frame.__init__(self,&nbsp;root) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.canvas&nbsp;=&nbsp;tk.Canvas(root,&nbsp;borderwidth=0,&nbsp;background="#ffffff") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.frame&nbsp;=&nbsp;tk.Frame(self.canvas,&nbsp;background="#ffffff") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.vsb&nbsp;=&nbsp;tk.Scrollbar(root,&nbsp;orient="vertical",&nbsp;command=self.canvas.yview) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.canvas.configure(yscrollcommand=self.vsb.set) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.vsb.pack(side="right",&nbsp;fill="y") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.canvas.pack(side="left",&nbsp;fill="both",&nbsp;expand=True) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.canvas.create_window((4,4),&nbsp;window=self.frame,&nbsp;anchor="nw",&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tags="self.frame") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.frame.bind("<Configure>",&nbsp;self.onFrameConfigure) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.populate() &nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;populate(self): &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'''Put&nbsp;in&nbsp;some&nbsp;fake&nbsp;data''' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;row&nbsp;in&nbsp;range(100): &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tk.Label(self.frame,&nbsp;text="%s"&nbsp;%&nbsp;row,&nbsp;width=3,&nbsp;borderwidth="1",&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;relief="solid").grid(row=row,&nbsp;column=0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t="this&nbsp;is&nbsp;the&nbsp;second&nbsp;column&nbsp;for&nbsp;row&nbsp;%s"&nbsp;%row &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tk.Label(self.frame,&nbsp;text=t).grid(row=row,&nbsp;column=1) &nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;onFrameConfigure(self,&nbsp;event): &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'''Reset&nbsp;the&nbsp;scroll&nbsp;region&nbsp;to&nbsp;encompass&nbsp;the&nbsp;inner&nbsp;frame''' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.canvas.configure(scrollregion=self.canvas.bbox("all"))if&nbsp;__name__&nbsp;==&nbsp;"__main__": &nbsp;&nbsp;&nbsp;&nbsp;root=tk.Tk() &nbsp;&nbsp;&nbsp;&nbsp;Example(root).pack(side="top",&nbsp;fill="both",&nbsp;expand=True) &nbsp;&nbsp;&nbsp;&nbsp;root.mainloop()程序解决方案以下是不使用对象的解决方案:import&nbsp;tkinter&nbsp;as&nbsp;tkdef&nbsp;populate(frame): &nbsp;&nbsp;&nbsp;&nbsp;'''Put&nbsp;in&nbsp;some&nbsp;fake&nbsp;data''' &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;row&nbsp;in&nbsp;range(100): &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tk.Label(frame,&nbsp;text="%s"&nbsp;%&nbsp;row,&nbsp;width=3,&nbsp;borderwidth="1",&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;relief="solid").grid(row=row,&nbsp;column=0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t="this&nbsp;is&nbsp;the&nbsp;second&nbsp;column&nbsp;for&nbsp;row&nbsp;%s"&nbsp;%row &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tk.Label(frame,&nbsp;text=t).grid(row=row,&nbsp;column=1)def&nbsp;onFrameConfigure(canvas): &nbsp;&nbsp;&nbsp;&nbsp;'''Reset&nbsp;the&nbsp;scroll&nbsp;region&nbsp;to&nbsp;encompass&nbsp;the&nbsp;inner&nbsp;frame''' &nbsp;&nbsp;&nbsp;&nbsp;canvas.configure(scrollregion=canvas.bbox("all"))root&nbsp;=&nbsp;tk.Tk()canvas&nbsp;=&nbsp;tk.Canvas(root,&nbsp;borderwidth=0,&nbsp;background="#ffffff")frame&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tk.Frame(canvas,&nbsp;background="#ffffff")vsb&nbsp;=&nbsp;tk.Scrollbar(root,&nbsp;orient="vertical",&nbsp;command=canvas.yview)canvas.configure &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(yscrollcommand=vsb.set)vsb.pack(side="right",&nbsp;fill="y")canvas.pack(side="left",&nbsp;fill="both",&nbsp;expand=True)canvas.create_window((4,4), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window=frame,&nbsp;anchor="nw")frame.bind("<Configure>",&nbsp;lambda&nbsp;event,&nbsp;canvas=canvas:&nbsp;onFrameConfigure(canvas))populate(frame)root.mainloop()注:若要在python2.x中执行此操作,请使用Tkinter而不是tkinter在导入语句中
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python