简体   繁体   English

滚动笔记本标签 Tkinter

[英]Scrolling Notebook Tabs Tkinter

I want to make a lot of notebook tabs, and I want to put them in canvas and to add a horizontal scrollbar so that I can scroll trough them.我想制作很多笔记本标签,我想把它们放在画布上并添加一个水平滚动条,以便我可以滚动它们。 I set the canvas size, but canvas size keep changing when I add new tab.我设置了画布大小,但是当我添加新标签时,画布大小会不断变化。 Also, scrollbar does not work, can you tell me what am I doing wrong?另外,滚动条不起作用,你能告诉我我做错了什么吗?

The program does not show me any error.该程序没有显示任何错误。 This is the code:这是代码:

from tkinter import *
from tkinter import ttk

myApp = Tk()
myApp.title(" Program ")                         
myApp.geometry("900x500")

CanvasTabs = Canvas(myApp, width=50, height=50)
CanvasTabs.grid(row=0,column=0)

tabs = ttk.Notebook(CanvasTabs, width=100, height=100)

tab1 = ttk.Frame(tabs)
tabs.add(tab1,text="  Tab 1  ")

tab2 = ttk.Frame(tabs)
tabs.add(tab2,text="  Tab 2  ")

tab3 = ttk.Frame(tabs)
tabs.add(tab3,text="  Tab 3  ")

tab4 = ttk.Frame(tabs)
tabs.add(tab4,text="  Tab 4  ")


hbar=Scrollbar(CanvasTabs,orient=HORIZONTAL)
hbar.pack(side=TOP,fill=X)
hbar.config(command=CanvasTabs.xview)

CanvasTabs.config(xscrollcommand=hbar.set)


tabs.pack(expand=1, fill="both")   

myApp.mainloop()

I code a widget to fix the problem.我编写了一个小部件来解决这个问题。 Here is a real solution: https://github.com/muhammeteminturgut/ttkScrollableNotebook这是一个真正的解决方案: https : //github.com/muhammeteminturgut/ttkScrollableNotebook

示范

# -*- coding: utf-8 -*-

# Copyright (c) Muhammet Emin TURGUT 2020
# For license see LICENSE
from tkinter import *
from tkinter import ttk

class ScrollableNotebook(ttk.Frame):
    def __init__(self,parent,*args,**kwargs):
        ttk.Frame.__init__(self, parent, *args)
        self.xLocation = 0
        self.notebookContent = ttk.Notebook(self,**kwargs)
        self.notebookContent.pack(fill="both", expand=True)

        self.notebookTab = ttk.Notebook(self,**kwargs)
        self.notebookTab.bind("<<NotebookTabChanged>>",self._tabChanger)

        slideFrame = ttk.Frame(self)
        slideFrame.place(relx=1.0, x=0, y=1, anchor=NE)
        leftArrow = ttk.Label(slideFrame, text="\u25c0")
        leftArrow.bind("<1>",self._leftSlide)
        leftArrow.pack(side=LEFT)
        rightArrow = ttk.Label(slideFrame, text=" \u25b6")
        rightArrow.bind("<1>",self._rightSlide)
        rightArrow.pack(side=RIGHT)
        self.notebookContent.bind( "<Configure>", self._resetSlide)

    def _tabChanger(self,event):
        self.notebookContent.select(self.notebookTab.index("current"))

    def _rightSlide(self,event):
        if self.notebookTab.winfo_width()>self.notebookContent.winfo_width()-30:
            if (self.notebookContent.winfo_width()-(self.notebookTab.winfo_width()+self.notebookTab.winfo_x()))<=35:
                self.xLocation-=20
                self.notebookTab.place(x=self.xLocation,y=0)
    def _leftSlide(self,event):
        if not self.notebookTab.winfo_x()== 0:
            self.xLocation+=20
            self.notebookTab.place(x=self.xLocation,y=0)

    def _resetSlide(self,event):
        self.notebookTab.place(x=0,y=0)
        self.xLocation = 0

    def add(self,frame,**kwargs):
        if len(self.notebookTab.winfo_children())!=0:
            self.notebookContent.add(frame, text="",state="hidden")
        else:
            self.notebookContent.add(frame, text="")
        self.notebookTab.add(ttk.Frame(self.notebookTab),**kwargs)

    def forget(self,tab_id):
        self.notebookContent.forget(tab_id)
        self.notebookTab.forget(tab_id)

    def hide(self,tab_id):
        self.notebookContent.hide(tab_id)
        self.notebookTab.hide(tab_id)

    def identify(self,x, y):
        return self.notebookTab.identify(x,y)

    def index(self,tab_id):
        return self.notebookTab.index(tab_id)

    def insert(self,pos,frame, **kwargs):
        self.notebookContent.insert(pos,frame, **kwargs)
        self.notebookTab.insert(pos,frame,**kwargs)

    def select(self,tab_id):
        self.notebookContent.select(tab_id)
        self.notebookTab.select(tab_id)

    def tab(self,tab_id, option=None, **kwargs):
        return self.notebookTab.tab(tab_id, option=None, **kwargs)

    def tabs(self):
        return self.notebookContent.tabs()

    def enable_traversal(self):
        self.notebookContent.enable_traversal()
        self.notebookTab.enable_traversal()

Taking Bryan's example on this post and modifying it to include your Notebook code we get a functioning scrollbar that will allow you to scroll over your Notebook widget if it exceeds the limit of the window.这篇文章中Bryan 的示例并修改它以包含您的 Notebook 代码,我们得到了一个功能正常的滚动条,如果它超出窗口的限制,您将允许您在 Notebook 小部件上滚动。

Bryan's example uses the pack() geometry manager however I personally find grid() easier to visualize so I replace pack with grid() in my example. Bryan 的示例使用了pack()几何管理器,但我个人认为grid()更易于可视化,因此我在示例中将 pack 替换为grid()

UPDATE:更新:

import tkinter as tk
import tkinter.ttk as ttk


class Example(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.canvas = tk.Canvas(self, borderwidth=0)
        self.frame = tk.Frame(self.canvas)

        self.vsb = tk.Scrollbar(self, orient="horizontal", command=self.canvas.xview)
        self.vsb.grid(row=1, column=0, sticky="nsew")

        self.canvas.configure(xscrollcommand=self.vsb.set)
        self.canvas.grid(row=0, column=0, sticky="nsew")
        self.canvas.create_window((3,2), window=self.frame, anchor="nw", tags="self.frame")

        self.frame.bind("<Configure>", self.frame_configure)
        self.populate()

    def populate(self):
        tabs = ttk.Notebook(self.frame, width=100, height=100)
        for tab in range(50):
            tabs.add(ttk.Frame(tabs), text=" Tab {}  ".format(tab))
        tabs.grid(row=0, column=0, sticky="ew")


    def frame_configure(self, event):
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))

if __name__ == "__main__":
    app = Example()
    app.mainloop()

Updated results:更新结果:

在此处输入图片说明

Per your request in the comments here is a Non-OOP example:根据您在评论中的请求,这里是一个非 OOP 示例:

import tkinter as tk
import tkinter.ttk as ttk


root = tk.Tk()
canvas = tk.Canvas(root, borderwidth=0)
frame = tk.Frame(canvas)

vsb = tk.Scrollbar(root, orient="horizontal", command=canvas.xview)
vsb.grid(row=1, column=0, sticky="nsew")

canvas.configure(xscrollcommand=vsb.set)
canvas.grid(row=0, column=0, sticky="nsew")
canvas.create_window((3,2), window=frame, anchor="nw", tags="frame")

tabs = ttk.Notebook(frame, width=100, height=100)
for tab in range(50):
    tabs.add(ttk.Frame(tabs), text=" Tab {}  ".format(tab))
tabs.grid(row=0, column=0, sticky="ew")

def frame_configure(event):
    global canvas
    canvas.configure(scrollregion=canvas.bbox("all"))

frame.bind("<Configure>", frame_configure)

root.mainloop()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM