如何在Python tkinter的Frame组件中添加scrollbar滚动条?
解决方案
Tkinter 原生普通Frame组件本身不支持滚动功能,你需要通过「Canvas + 内部子Frame + 滚动条」的组合结构实现滚动效果,以下是修改后的完整可运行代码:
1. 替换原有Frame定义部分
将你原来创建fr的代码替换为如下滚动区域结构:
from tkinter import * from tkinter import messagebox import urllib.error, urllib.parse ,urllib.request from bs4 import BeautifulSoup b="#0c1231" root = Tk() root.title("Stock World") root.geometry("1350x722+5+5") root.configure(bg=b) # ------------------- 新增滚动区域结构 ------------------- # 外层容器(对应原来fr的放置位置) outer_frame = Frame(root, bg=b) outer_frame.place(relx=0.01,rely=0.11,width=1310,height=635) # 绘制画布承载可滚动内容 canvas = Canvas(outer_frame, bg=b, highlightthickness=0) canvas.pack(side=LEFT, fill=BOTH, expand=YES) # 绑定垂直滚动条 scrollbar = Scrollbar(outer_frame, orient=VERTICAL, command=canvas.yview) scrollbar.pack(side=RIGHT, fill=Y) canvas.configure(yscrollcommand=scrollbar.set) # 支持鼠标滚轮滚动 def _on_mousewheel(event): canvas.yview_scroll(int(-1*(event.delta/120)), "units") canvas.bind_all("<MouseWheel>", _on_mousewheel) # 内部可滚动Frame,所有数据Label都挂载到这个组件上 scrollable_fr = Frame(canvas, bg=b) canvas.create_window((0, 0), window=scrollable_fr, anchor="nw") # 自动更新滚动区域范围 def update_scrollregion(e): canvas.configure(scrollregion=canvas.bbox("all")) scrollable_fr.bind("<Configure>", update_scrollregion) # ---------------------------------------------------------
2. 修改数据加载函数
调整get_web_result函数,替换Label的父组件,同时新增旧数据清空逻辑避免内容叠加:
def get_web_result(): # 先清空之前加载的旧数据 for widget in scrollable_fr.winfo_children(): widget.destroy() for i in range(1,2): try: lnk="https://www.moneycontrol.com/broker-research/latestResearchReport/"+str(i) url = urllib.request.urlopen(lnk) except: messagebox.showwarning("Notification","Check your internet connection and try again later !!!") return bs = BeautifulSoup(url,"html.parser") tg = bs('tbody') for line in tg: lne = line.text with open("stock.txt","w", encoding="utf-8") as fopen: fopen.writelines(lne.strip()) with open("stock.txt","r", encoding="utf-8") as fopen: fcontent = fopen.readlines() x=0.01 y=0.02 a=1 for l in fcontent: l = l.strip() if len(l)>0: # 所有Label的父组件改为scrollable_fr if a==1: #date lb = Label(scrollable_fr,text=l, font=("arial",10),fg="white",bg=b) lb.place(relx=0.005,rely=y) elif a==2: #company lb = Label(scrollable_fr,text=l, font=("arial",10),fg="white",bg=b) lb.place(relx=0.09,rely=y) elif a==3: #broker lb = Label(scrollable_fr,text=l, font=("arial",10),fg="white",bg=b) lb.place(relx=0.20,rely=y) elif a==4: #buy or sell lb = Label(scrollable_fr,text=l, font=("arial",10),fg="white",bg=b) lb.place(relx=0.31,rely=y) elif a==5: #report price lb = Label(scrollable_fr,text=l, font=("arial",10),fg="white",bg=b) lb.place(relx=0.38,rely=y) elif a==6: #cmp lb = Label(scrollable_fr,text=l, font=("arial",10),fg="white",bg=b) lb.place(relx=0.475,rely=y) elif a==7: #target price lb = Label(scrollable_fr,text=l, font=("arial",10),fg="white",bg=b) lb.place(relx=0.56,rely=y) elif a==8: #profit lb = Label(scrollable_fr,text=l, font=("arial",10),fg="white",bg=b) lb.place(relx=0.62,rely=y) elif a==9: #realized return lb = Label(scrollable_fr,text=l, font=("arial",10),fg="white",bg=b) lb.place(relx=0.70,rely=y) elif a==10: #sensex return lb = Label(scrollable_fr,text=l, font=("arial",10),fg="white",bg=b) lb.place(relx=0.81,rely=y) elif a==11: lb = Label(scrollable_fr,text=l, font=("arial",10),fg="white",bg=b) lb.place(relx=0.98,rely=y) elif a==12: lb = Label(scrollable_fr,text=l, font=("arial",10),fg="white",bg=b) lb.place(relx=0.99,rely=y) elif a==13: lb = Label(scrollable_fr,text=l, font=("arial",10),fg="white",bg=b) lb.place(relx=0.99,rely=y) a=a+1 if a == 14: y=y+0.03 a=1
3. 剩余界面代码保持不变
你原来的按钮、表头Label代码无需修改,直接保留即可运行。
内容的提问来源于stack exchange,提问作者Somesh_Bang
相关产品推荐
相关产品推荐

