首页 > 解决方案 > 无法在 tkinter 中将滚动条添加到文本小部件(包含多个框架)

问题描述

我正在尝试为我的 python 脚本创建一个 GUI。当我按下“获取问题类型”按钮时,我从一个函数中获取一个字典(在代码中我刚刚获取了一个示例字典)。
对于每个项目(比如 p1),我为列表中的所有元素创建一个复选按钮。我为每个项目创建一个框架,所有这些框架都在一个文本框内(因为框架不支持在 tkinter 中滚动)
当字典大小非常大时,文本框只会缩放并超出窗口大小并且滚动条不起作用。
我如何让滚动条工作? 应用程序的输出

这是上述应用程序的代码

from tkinter import *
from tkscrolledframe import ScrolledFrame
from tkinter import messagebox
import os

root=Tk()
selected_issuetypes={}
bool_dict_selected_issuetypes={}
dict_issuetypes={}
def get_issuetypes():
    for widget in frame.winfo_children():
        widget.destroy()
    global dict_issuetypes
    #dict_issuetypes = function()
    dict_issuetypes={
        "p1":["a","b","c","d"],
        "p2":["a","b","c"],
        "p3":["a","b"],
        "p4":["a","b","c","d"],
        "p5":["a","b","c"],
        "p6":["a","b"],
        "p7":["a","b","c","d"],
        "p8":["a","b","c"],
        "p9":["a","b"],
        "p10":["a","b","c","d"],
        "p11":["a","b","c"],
        "p12":["a","b"],
        "p13":"not valid"
    }
    for project,issuetypes in dict_issuetypes.items():
        if str(type(issuetypes))=="<class 'list'>":
            bool_dict_selected_issuetypes[project]=[BooleanVar() for i in range(len(issuetypes))]
            selected_issuetypes[project]=[]
    r=c=0
    fr=0
    color="white"
    for project,issuetypes in dict_issuetypes.items():
        frame1=Frame(frame,bg=color)
        frame1.grid(row=fr,columnspan=3,sticky='we')
        if str(type(issuetypes))=="<class 'list'>":
            Label(frame1,text=project,width=10,anchor='w',bg=color).grid(row=r,column=c)
            for i in range(0,len(issuetypes)):
                Checkbutton(frame1,text=issuetypes[i],variable=bool_dict_selected_issuetypes[project][i],bg=color).grid(row=r,column=c+1,sticky='w')
                r=r+1
        else:
            Label(frame1,text=issuetypes+'\n',bg=color).grid(row=r,column=c+1)
            r=r+1
        r=r+1
        fr=fr+1
        if color=="white":
            color="grey"
        else:
            color="white"


height = root.winfo_screenheight()
width = root.winfo_screenwidth()
root.geometry(str(width)+'x'+str(height-100)+'+'+'0'+'+'+'0')
project_label=Label(root,text="enter project keys/id's :-")
project_label.grid(row=0,column=0,padx=10,pady=10)
project_entry=Entry(root,width=100)
project_entry.insert(0,"enter here")
project_entry.grid(row=0,column=1,padx=10,pady=10)
get_issues_button=Button(root,text="get issuetypes",command=get_issuetypes)
get_issues_button.grid(row=0,column=2,padx=10,pady=10)
frame=Text(root)
frame.grid(row=1,columnspan=3,sticky='nsew',padx=2,pady=2)
frame.grid_columnconfigure(0, weight=1)
frame.grid_rowconfigure(0, weight=1)
v=Scrollbar(root,command=frame.yview)
v.grid(row=1, column=3, sticky='nsew')
frame['yscrollcommand']=v.set
frame.config(font=("consolas", 12), undo=True, wrap='word')

root.mainloop()

标签: pythontkinterscrollbartktkinter-canvas

解决方案


您不能使用grid将小部件放入文本小部件中。文本小部件只能滚动使用添加的其他小部件window_create。您还需要确保在每个添加了window_create.

这是一个人为的例子:

import tkinter as tk

root = tk.Tk()
text = tk.Text(root)
ysb = tk.Scrollbar(root, orient='vertical', command=text.yview)
text.configure(yscrollcommand=ysb.set)

ysb.pack(side="right", fill="y")
text.pack(side="left", fill="both", expand=True)

vars = []
for i in range(100):
    var = tk.IntVar(value=0)
    vars.append(var)
    f = tk.Frame(text)
    cb = tk.Checkbutton(f, onvalue=1, offvalue=0, text=f"Item {i}", variable=var)
    cb.pack(side="left")
    text.window_create("end", window=f)
    text.insert("end", "\n")

root.mainloop()

截屏


推荐阅读