真的不会英语
2021-08-20 16:06
采纳率: 100%
浏览 197
已结题

python tkinter ttk notebook选项卡绑定事件

我的想法是,当notebook的选项卡被单击后,触发事件或者返回选项卡的内容。

  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • Smart-Space 2021-08-20 17:24
    已采纳

    很遗憾,Notebook唯一的一个自定事件<<NotebookTabChanged>>无法满足要求。你可以尝试自己手动写一个notebook(比较复杂),并从中绑定事件。

    实际上,这个是无解的,百分之百无解,但是你可以参考下列代码(我自己重新实现的notebook,有缺陷。目前没有绑定事件,你可以在此基础上自行改善):

    class Notebook2(Frame):
        """
        Notebook2 是对 Notebook 的升级
        该组件可以显示更对标签,应为使用了滚动条和文本框创建标签组件
        标签组件可以自定义是否可以关闭,参数与Label相同
        通过加入frame即可(必须是frame,其它控件使用tkraise()基本无效),frame的父窗口必须是 Notebook2.show
        目前建议使用place布局
        颜色等可以直接使用类中的组件修改
        """
    
        def __init__(self,master,**kw):
            Frame.__init__(self,master,**kw)
            self.tabbar=Text(self,font=('宋体',2),wrap='none',bg='#D4D4E3',cursor='arrow',state='disable',bd=0)
            self.tabbar.place(x=0,y=0,relwidth=1,height=23)
            self.vbar=Scrollbar(self,orient='horizontal',width=9)#,bg='#7496D2')
            self.vbar['command']=self.tabbar.xview
            self.tabbar['xscrollcomman']=self.vbar.set
            self.vbar.place(x=0,y=23,relwidth=1)
            self.show=Frame(self,relief='groove',bg='#f0f0fe')#等待指定位置后再现实
            self.frames={}# text => frame
            self.tabs={}#label组件集   num => label
    
        def show_area(self):
            self.update()
            self.show.place(x=0,y=33,relwidth=1,height=self.winfo_height()-33)
        def grid(self,**kw):
            Frame.grid(self,**kw)
            self.show_area()
        def pack(self,**kw):
            Frame.pack(self,**kw)
            self.show_area()
        def place(self,**kw):
            Frame.place(self,**kw)
            self.show_area()
    
        def show_first(self,text):#在一些影响选项卡的操作后,显示第一个选项卡的frame
            if len(self.tabs.keys())==1:
                self.show_tab(text)
    
        def show_tab(self,text):#显示选项卡文本对应的frame
            frame=self.frames[text]
            for i in self.tabs.values():
                if i['text']!=text:
                    i['background']='#f0f0f0'
                else:
                    i['background']='white'
            frame.place(x=0,y=0,relwidth=1,relheight=1)
            frame.tkraise()
    
        def deltab(self,text):#删除text选项卡
            del self.frames[text]
            for i in list(self.tabs.values()):
                if i['text']==text:
                    num=list(self.tabs.keys())[list(self.tabs.values()).index(i)]
                    self.tabbar.delete('1.'+num,'1.'+num+'1c')
                    del self.tabs[num]
                    i.destroy()
    
        def add_frame(self,text,num,frame,close=False,**kw):#working
            """
            text:选项卡文本
            num:对应序号
            frame:对应frame
            close:是否允许关闭
            """
            self.tabbar['state']='normal'
            if type(num)==int:
                num=str(num*2)
            else:
                try:
                    num=str(int(num)*2)
                except:
                    raise NumError('"num" must be a number')
            if num in self.tabs.keys():#如果过顺序重复,重新排序
                numbers=list(self.tabs.keys())[list(self.tabs.keys()).index(num):]
                for i in numbers:
                    self.tabs[str(int(i)+2)]=self.tabs[i]
            tab=Label(self.tabbar,anchor='n',text=text,bg='#f0f0f0',bd=3,font=('微软雅黑',10),**kw)
            self.tabbar.update()
            self.tabbar.window_create('1.'+num,window=tab)
            if close==True:#是否可以删除
                text=text+'    '
                tab['text']=text
                #如果用Button,不管是tkinter的还是ttk的,都不好看
                closeb=Label(tab,text='x',width=2)
                tab.update()
                closeb.place(x=tab.winfo_width()-20,y=-3,height=23)
                closeb.bind('<Enter>',lambda event:closeb.configure(foreground='red'))
                closeb.bind('<Leave>',lambda event:closeb.configure(foreground='black'))
                closeb.bind('<Button-1>',lambda event:self.deltab(text))
            tab.bind('<Button-1>',lambda event:self.show_tab(text))
            self.tabbar.insert('1.'+num+'+1c',' ')
            self.tabbar['state']='disabled'
            self.tabs.update({num:tab})#更新标签集
            self.frames.update({text:frame})
            self.show_first(text)
    

    这个类是我之前写的,实现以下功能:

    • 标签页用滚动条绑定,可以无限增加
    • 标签页可删除(存在bug)
    • 实现notebook能够实现的功能

    没想到现在用在这里。

    其中,==show_tab==函数就是点击新选项卡后的函数操作,你可以在其中增加你需要的绑定事件。

    希望能够帮助到你。

    评论
    解决 1 无用 1
    打赏 举报
查看更多回答(1条)

相关推荐 更多相似问题