使用滚动条时文本小部件内容覆盖的 tkinter Tab

tkinter Tab covered by the text widget content when using scrollbar

请问我的代码有一点问题,我希望你们能帮助我,伙计们, 我正在使用滚动条滚动我的文本小部件中的图像,但问题是当我滚动时选项卡 window 被图像覆盖。

this last picture shows the problem, and i want the tabs to remain showing when i scroll and the images should stay inside the tab. here's the code i used:

import tkinter as tk
from PIL import ImageTk, Image
from os import listdir
from os.path import isfile, join
from tkinter import ttk

def getPaths():
    path = "C://Users/poste/Desktop/trainCascade/p"
    onlyfiles = [f for f in listdir(path) if isfile(join(path, f))]
    return onlyfiles

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        style = ttk.Style()
        style.theme_create('pastel', settings={
            ".": {
                "configure": {
                    "background": 'white',  # All except tabs
                    "font": 'red'
                }
            },
            "TNotebook": {
                "configure": {
                    "background": '#848a98',  # Your margin color
                    "tabmargins": [2, 5, 0, 0],  # margins: left, top, right, separator
                }
            },
            "TNotebook.Tab": {
                "configure": {
                    "background": '#d9ffcc',  # tab color when not selected
                    "padding": [10, 2],
                    "font": "white"
                },
                "map": {
                    "background": [("selected", '#ccffff')],  # Tab color when selected
                    "expand": [("selected", [1, 1, 1, 0])]  # text margins
                }
            }
        })

    style.theme_use('pastel')

    tabControl = ttk.Notebook(self)

    tab1 = ttk.Frame(tabControl)
    tab2 = ttk.Frame(tabControl)

    tabControl.add(tab1, text='Tab 1')
    tabControl.add(tab2, text='Tab 2')
    tabControl.pack(expand=1, fill="both")

    text = tk.Text(tab1, wrap="none")
    vsb = tk.Scrollbar(tab1, orient="vertical", command=text.yview)
    text.configure(yscrollcommand=vsb.set)
    vsb.pack(side="right", fill="y")
    text.pack(fill="both", expand=True)

    img = []
    resized = []
    final = []
    label = []
    flag = 0
    for i in range(len(getPaths())):
        img.append(Image.open("C://Users/poste/Desktop/trainCascade/p/"+getPaths()[i]))
        resized.append(img[i].resize((107, 80), Image.ANTIALIAS))
        final.append(ImageTk.PhotoImage(resized[i]))

        label.append(tk.Label(image=final[i], bg='white'))
        label[i].image = final[i]
        text.window_create("end", window=label[i])
        flag+=1
        if flag==5:
            text.insert("end", "\n")
            flag=0

    text.configure(state="disabled")

if __name__ == "__main__":
    root = tk.Tk()
    root.geometry("575x400")
    Example(root).pack(fill="both", expand=True)
    root.mainloop()

问题似乎是由于在使用图像创建这些标签时缺少 master 参数引起的。

作为一个最小的工作示例:

import tkinter as tk

root = tk.Tk()

label = tk.Label(root, text="If you scroll down the text box, this will " \
                            "be covered.", anchor="w")
label.pack(fill="x")

text = tk.Text(root)
text.pack()

for i in range(50):
    # Adding `text` as the first parameter here solves the problem
    label = tk.Label(text=f"Text label number {i}")
    text.window_create("end", window=label)
    text.insert("end", "\n")

root.mainloop()

当您未指定 master 参数时,tkinter 将使用您为 master 创建的第一个 window。问题是文本小部件告诉 Label 绘制自身,给出超出其边界的坐标。 Label 检查它是否在 master 的边界内,但因为它的 master 不是文本小部件,所以它可以自由地覆盖其他小部件。我认为这是 tcl 中的错误,tkinter 使用的库。

修复: 创建小部件时始终传入 master 参数。