使 tabControl 选项卡的内容可滚动,同时它仍然用作选项卡 - tkinter

Make the contents of a tabControl tab scrollable while it still functions as a tab - tkinter

TKINTER - 我有一个简单的 GUI,它使用了一些 tabControl 选项卡。我想让选项卡(多个小部件)的内容可滚动。正如许多 SO 用户和其他网站所建议的那样,我已经弄清楚如何使用 canvas 中的 window 使具有多个小部件的整个 window 可滚动。但是,如果我对 tabControl 选项卡的内容尝试此技术,它不起作用。

代表:

from tkinter import *
from tkinter import ttk
import tkinter as tk

# main window
window = tk.Tk()
window.geometry('400x400')
tabControl = ttk.Notebook(window)

# create tabs
tab_A = ttk.Frame(tabControl)
tab_B = ttk.Frame(tabControl)
tab_C = ttk.Frame(tabControl)
tabControl.add(tab_A, text='A')
tabControl.add(tab_B, text='B')
tabControl.add(tab_C, text='C')
tabControl.grid()

# tab A
for i in range(5):
    dir_frame = LabelFrame(tab_A, text=f'LabelFrame {i}', pady=3, padx=5, relief='solid', highlightthickness=5, font=100, fg='darkblue')
    dir_frame.grid(column=0, row=i, columnspan=2, sticky='ew')
    Label(master=dir_frame, text="Text text \t\t\t").grid(row=0, column=0, sticky='w', pady=15)
    Button(master=dir_frame, text="Button").grid(row=0, column=1, sticky='e', padx=5)

# tab B
for i in range(7):
    Label(master=tab_B, text=f"Text {i}\t\t\t\t").grid(row=i, column=0, sticky='w', pady=18)
    chb2 = Checkbutton(tab_B).grid(row=i, column=1, sticky='e', padx=15)

# tab C
scroll = Scrollbar(tab_C)
scroll.grid(column=1, sticky='ns')
text = Text(tab_C, width=45, wrap=WORD, yscrollcommand=scroll.set)
for i in range(5):
    text.insert(END, f'\n{i}.\n')
    text.insert(END, f'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.')
    text.insert(END, f'\n\n\n\n')
text.grid(column=0, row=0, sticky="nesw")
text.configure(state=DISABLED)
scroll.config(command=text.yview)

# run
window.mainloop()

因此,如果我创建一个主框架和带有滚动条的 canvas,请配置此 canvas,在 canvas 中创建另一个框架并将该新框架添加到 window 在 canvas 中(这似乎是这样做的方式),它是可滚动的,但显示在我的选项卡下方。此外,标签功能不再show/hide内容。

这是我的代码:

from tkinter import *
from tkinter import ttk
import tkinter as tk

# main window
window = tk.Tk()
window.geometry('400x400')
tabControl = ttk.Notebook(window)

# create tabs
tab_A = ttk.Frame(tabControl)
tab_B = ttk.Frame(tabControl)
tab_C = ttk.Frame(tabControl)
tabControl.add(tab_A, text='A')
tabControl.add(tab_B, text='B')
tabControl.add(tab_C, text='C')
tabControl.grid()

# create a main frame
main_frame = Frame(window)
main_frame.columnconfigure(0, weight=1)
main_frame.grid(column=0, row=1, sticky='nsew')

# create a canvas
my_canvas = Canvas(main_frame)
my_canvas.grid(column=0, row=1, sticky='nsew')

# add a scrollbar to the canvas
my_scrollbar = ttk.Scrollbar(main_frame, orient=VERTICAL, command=my_canvas.yview)
my_scrollbar.grid(column=0, row=1, sticky='ens')

# configure the canvas
my_canvas.configure(yscrollcommand=my_scrollbar.set)
my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion=my_canvas.bbox("all")))

# create another frame inside the canvas
second_frame = Frame(my_canvas)

# add that new frame to a window in the canvas
my_canvas.create_window((0,0), window=second_frame, anchor="nw")

# tab A
for i in range(5):
    dir_frame = LabelFrame(second_frame, text=f'LabelFrame {i}', pady=3, padx=5, relief='solid', highlightthickness=5, font=100, fg='darkblue')
    dir_frame.grid(column=0, row=i, columnspan=2, sticky='ew')
    Label(master=dir_frame, text="Text text \t\t\t").grid(row=0, column=0, sticky='w', pady=15)
    Button(master=dir_frame, text="Button").grid(row=0, column=1, sticky='e', padx=5)

# tab B
for i in range(7):
    Label(master=tab_B, text=f"Text {i}\t\t\t\t").grid(row=i, column=0, sticky='w', pady=18)
    chb2 = Checkbutton(tab_B).grid(row=i, column=1, sticky='e', padx=15)

# tab C
scroll = Scrollbar(tab_C)
scroll.grid(column=1, sticky='ns')
text = Text(tab_C, width=45, wrap=WORD, yscrollcommand=scroll.set)
for i in range(5):
    text.insert(END, f'\n{i}.\n')
    text.insert(END, f'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.')
    text.insert(END, f'\n\n\n\n')
text.grid(column=0, row=0, sticky="nesw")
text.configure(state=DISABLED)
scroll.config(command=text.yview)

# run
window.mainloop()

选项卡 C 仅包含一个文本小部件,其功能就像我也希望有 A en B。它是可滚动的,选项卡的功能类似于选项卡。

有什么建议吗?

您已将 canvas 放在主框架中而不是选项卡中。如果您希望它位于选项卡中,它需要成为选项卡框架的子项。

main_frame = Frame(tab_A)
#                  ^^^^^

与所问的问题无关,我建议使用 pack 而不是 grid 作为唯一的子窗口小部件,或者包含窗口小部件中仅有的几个子窗口小部件之一。它需要的代码少一点,而且更加简单,因为您不必担心向唯一的行和列添加权重。

例如,只需一行代码即可让笔记本填充 window 并在调整大小时扩大和缩小:

tabControl.pack(fill="both", expand=True)

main_frame也是如此,因为它是选项卡框架中唯一的小部件。

main_frame.pack(fill="both", expand=True)

最后,pack 还使布局小部件及其滚动条变得非常容易:

my_scrollbar.pack(side="right", fill="y")
my_canvas.pack(side="left", fill="both", expand=True)