如何在tkinter窗口中添加滚动条?

12

我有一个tkinter程序:

import urllib.request
from tkinter import *


root = Tk()
root.iconbitmap(default='icon.ico')
root.wm_title('Got Skills\' Skill Tracker')
frame = Frame(width="500",height="500")
frame.pack()


def show():
  name = "zezima"
  page = urllib.request.urlopen('http://hiscore.runescape.com/index_lite.ws?player=' + name)
  page = page.readlines()

  skills = []
  for line in page:
    skills.append([line.decode("utf-8").replace("\n", "").split(",")])

  skills = skills[0:25]

  for item in skills:
    toPrint = item[0][0],"-",item[0][1],"-",item[0][1],"\n"
    w = Message(frame, text=toPrint)
    w.pack()


menu = Menu(root)
root.config(menu=menu)

filemenu = Menu(menu)
menu.add_cascade(label="Commands", menu=filemenu)
filemenu.add_command(label="Show Skills", command=show)


root.mainloop()
当我运行上述脚本时,它显示了这个(很好): alt text http://img708.imageshack.us/img708/8821/tkinter1.png 当我点击命令>显示技能时,它变成了这样。虽然它显示了正确的内容,但是...我可以想象你看到了问题。
两个问题: -如何向框架添加滚动条,并保持框架大小固定? (理想情况下,保持第一幅图像的大小,添加show()的输出,将滚动条添加到程序的第一幅图像。) -使用以下代码:
  for item in skills:
    toPrint = item[0][0],"-",item[0][1],"-",item[0][2],"\n"
    w = Message(frame, text=toPrint)
    w.pack()

这是输出我所需内容的最佳方式吗?列表 (skills) 看起来像 [[1,2,3],[4,5,6]..],我想在一行上显示1-2-3,另一行上显示4-5-6等。

但是,我不希望它们之间有额外的空行,我想知道我现在的方法是否是最佳实践。

2个回答

12

要添加滚动条,请使用tkinter.tix.ScrolledWindow。

要去除多余的空格,请删除额外的“\n”并显示字符串,而不是元组。以下是完整代码:

import urllib.request
from tkinter import *
from tkinter.tix import *

root = Tk()
root.iconbitmap(default='icon.ico')
root.wm_title('Got Skills\' Skill Tracker')
frame = Frame(width="500",height="500")
frame.pack()
swin = ScrolledWindow(frame, width=500, height=500)
swin.pack()
win = swin.window


def show():
  name = "zezima"
  page = urllib.request.urlopen('http://hiscore.runescape.com/index_lite.ws?player=' + name)
  page = page.readlines()

  skills = []
  for line in page:
    skills.append([line.decode("utf-8").replace("\n", "").split(",")])

  skills = skills[0:25]

  for item in skills:
    toPrint = item[0][0],"-",item[0][1],"-",item[0][1]
    w = Message(win, text=' '.join(toPrint), width=500)
    w.pack()


menu = Menu(root)
root.config(menu=menu)

filemenu = Menu(menu)
menu.add_cascade(label="Commands", menu=filemenu)
filemenu.add_command(label="Show Skills", command=show)


root.mainloop()

我原以为需要那个\n来防止它们都显示在同一行。:P。无论如何,非常感谢。它运行得很好。 :) - Andrew
你为什么在框架的宽度和高度中使用了字符串? - Gabe Morris
我收到了_tkinter.TclError: invalid command name "tixScrolledWindow"的错误消息。 - TheTechRobo the Nerd
@TheTechRobo36414519 我在自己的代码中实现时也遇到了同样的错误。你找到任何解决方案了吗? - abc
@abc - 我最终使用了一个模块,似乎我的系统的tkinter构建可能没有tix(这很有道理,它已经被弃用了一段时间,没有维护者)。所以这是我使用的模块 - 这是我的分支,因为原始的已经被存档,所以问题和PR无法提交。(编辑:我很蠢,在这里:https://github.com/TheTechRobo/tkScrolledFrame) - TheTechRobo the Nerd
显示剩余2条评论

1
这里是一个用于滚动框架的类。只需像传统的tkinter样式一样传递窗口对象,并使用obj.frame作为新小部件的窗口即可。
class ScrollableFrame:
    """
    # How to use class
    from tkinter import *
    obj = ScrollableFrame(master,height=300 # Total required height of canvas,width=400 # Total width of master)
    objframe = obj.frame
    # use objframe as the main window to make widget
    """
    def __init__ (self,master,width,height,mousescroll=0):
        self.mousescroll = mousescroll
        self.master = master
        self.height = height
        self.width = width
        self.main_frame = Frame(self.master)
        self.main_frame.pack(fill=BOTH,expand=1)

        self.scrollbar = Scrollbar(self.main_frame, orient=VERTICAL)
        self.scrollbar.pack(side=RIGHT,fill=Y)

        self.canvas = Canvas(self.main_frame,yscrollcommand=self.scrollbar.set)
        self.canvas.pack(expand=True,fill=BOTH)

        self.scrollbar.config(command=self.canvas.yview)

        self.canvas.bind('<Configure>', lambda e: self.canvas.configure(scrollregion = self.canvas.bbox("all")))

        self.frame = Frame(self.canvas,width=self.width,height=self.height)
        self.frame.pack(expand=True,fill=BOTH)
        self.canvas.create_window((0,0), window=self.frame, anchor="nw")

        self.frame.bind("<Enter>", self.entered)
        self.frame.bind("<Leave>", self.left)

    def _on_mouse_wheel(self,event):
        self.canvas.yview_scroll(-1 * int((event.delta / 120)), "units")

    def entered(self,event):
        if self.mousescroll:
            self.canvas.bind_all("<MouseWheel>", self._on_mouse_wheel)
        
    def left(self,event):
        if self.mousescroll:
            self.canvas.unbind_all("<MouseWheel>")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接