Python 如何在tkinter中处理来自不同类的回调和事件绑定?

Python 如何在tkinter中处理来自不同类的回调和事件绑定?,python,tkinter,Python,Tkinter,按照Bryan Oakley对这篇文章的回答,我想将tab1的内容移动到它自己的类中,但是让say_hello和get_item保持原样。我该怎么做 import tkinter as tk from tkinter import ttk, N, S, END, EXTENDED class MainApplication(tk.Frame): def __init__(self, root, *args, **kwargs): tk.Frame.__init__(se

按照Bryan Oakley对这篇文章的回答,我想将tab1的内容移动到它自己的类中,但是让say_hello和get_item保持原样。我该怎么做

import tkinter as tk
from tkinter import ttk, N, S, END, EXTENDED

class MainApplication(tk.Frame):
    def __init__(self, root, *args, **kwargs):
        tk.Frame.__init__(self, root, *args, **kwargs)
        self.root = root
        self.nb = ttk.Notebook(root)

        self.tab1 = ttk.Frame(self.nb)
        self.tab2 = ttk.Frame(self.nb)

        self.nb.add(self.tab1, text='TAB1')
        self.nb.add(self.tab2, text='TAB2')

        self.nb.grid(row=0, column=0)

        #contents of tab1 - which I would like to place in their own class
        self.frame = tk.Frame(self.tab1)
        self.frame.grid(row=0, column=0)

        self.button = tk.Button(self.frame, text='Hello', command=self.say_hello)
        self.button.grid(row=0, column=0)

        self.items = ['A','B','C']

        self.listbox = tk.Listbox(self.frame, selectmode=EXTENDED, exportselection=0)
        self.listbox.grid(row=1, column=0)

        self.scrollbar = tk.Scrollbar(self.frame, orient='vertical')
        self.scrollbar.grid(row=1, column=1, sticky=N+S)
        self.listbox.config(yscrollcommand=self.scrollbar.set)
        self.scrollbar.config(command=self.listbox.yview)
        self.listbox.bind('<<ListboxSelect>>', self.get_item)

        for item in self.items:
            self.listbox.insert(END, item) 


        #contents of tab2 - which should be in their own class
        #...
        #...


    def say_hello(self):
        print('hello')

    def get_item(self, evt):
        w = evt.widget
        index = int(w.curselection()[0])
        print('item selected = {}'.format(self.items[index]))

if __name__ == "__main__":
    root = tk.Tk() 
    MainApplication(root)
    root.mainloop()
将tkinter作为tk导入
从tkinter导入ttk,N,S,END,扩展
类main应用程序(tk.Frame):
定义初始化(self,root,*args,**kwargs):
tk.Frame.\uuuuu init\uuuuu(self,root,*args,**kwargs)
self.root=根
self.nb=ttk.Notebook(根目录)
self.tab1=ttk.Frame(self.nb)
self.tab2=ttk.Frame(self.nb)
self.nb.add(self.tab1,text='tab1')
self.nb.add(self.tab2,text='tab2')
self.nb.grid(行=0,列=0)
#tab1的内容-我想把它放在他们自己的课堂上
self.frame=tk.frame(self.tab1)
self.frame.grid(行=0,列=0)
self.button=tk.button(self.frame,text='Hello',command=self.say_Hello)
self.button.grid(行=0,列=0)
self.items=['A','B','C']
self.listbox=tk.listbox(self.frame,selectmode=EXTENDED,exportselection=0)
self.listbox.grid(行=1,列=0)
self.scrollbar=tk.scrollbar(self.frame,orient='vertical')
self.scrollbar.grid(行=1,列=1,粘性=N+S)
self.listbox.config(yscrollcommand=self.scrollbar.set)
self.scrollbar.config(命令=self.listbox.yview)
self.listbox.bind(“”,self.get\u项)
对于self.items中的项目:
self.listbox.insert(结束,项)
#tab2的内容-应该在他们自己的类中
#...
#...
def说你好(self):
打印('你好')
def get_项目(自身、evt):
w=evt.widget
index=int(w.curselection()[0])
打印('itemselected={}'。格式(self.items[index]))
如果名称=“\uuuuu main\uuuuuuuu”:
root=tk.tk()
主应用程序(根)
root.mainloop()
编辑:


感谢萨阿德的详细回复。我运行了你的代码,研究了它,学到了很多东西。然而,我修改了我的问题,使其更加集中

根据我的说法,我认为每个人都有自己的写作风格和组织文件和课程的方式。我组织代码的方式可能不是最好的。但我会尽我最大的努力使它更有条理,更简单。尽管没有关于如何组织Tkinter应用程序的硬性规定。但是,是的,OOP是组织大型项目的最佳方式,因为它们使代码更小,更容易理解

您可以在一个单独的文件(Tab1.py,Tab2.py,…)中为每个选项卡
(Tab1,Tab2,…)
创建一个类,但我希望将所有选项卡都放在一个名为tabs.py的文件中。这样我就可以像这样导入它们

导入选项卡
tabs.Tab1()
tabs.Tab2()
...
请仔细阅读代码中的每条注释和我的观点,以获得您的大部分答案。

我已将您的代码分为4部分

  • 首先,我为所有选项卡创建了一个基本框架类。在这个基本框架类中,我们可以配置所有选项卡共同需要的东西。例如,假设您希望每个选项卡中有一个背景颜色为“浅黄色”的框架。因此,您可以创建一个基类,并将其作为baseframe.py放在一个单独的文件中。就像这样

    #baseframe.py
    将tkinter作为tk导入
    类基架(tk.Frame):
    “这是选项卡的基本框架。”
    def _初始功率(自,主=无,**kw):
    超级()
    #这将是你的底架,如果你需要的话。
    #在此处执行所有选项卡的通用操作。
    #例如,如果希望每个选项卡具有相同的颜色。
    #这些只是一些示例,请根据需要进行更改。
    self['bg']='lightyellow'
    自我['relief']='sunken'
    自我['borderwidth']=5
    ...
    def显示信息(自我):
    “此功能对于每个选项卡都是通用的”
    #你不一定需要这个,
    #这只是向你展示可能性。
    #在该函数中执行您希望在每个选项卡中都包含的操作。
    ...
    ...
    打印('show_info',self)
    返回
    
  • 有一个单独的文件,其中有一个创建通用列表框的函数,这有意义吗

    我认为一个CustomListbox类会很好,你可以很有创造性地创建这个类,但我保持它的简单性。我在CustomListbox类中添加了一个滚动条,并对其进行了配置

    您可以为此创建文件customlistbox.py。或者将baseframe.py的名称更改为basewidgets.py,并将
    baseframe
    CustomListbox
    保存在一个文件中

    #customlistbox.py
    将tkinter作为tk导入
    类CustomListbox(tk.Listbox):
    “已配置垂直滚动条的Tkinter列表框。”
    def uuu init uuuu(self,master=None,cnf={},**kw):
    超级()
    #配置滚动条
    self.scrollbar=tk.scrollbar(self.master,orient='vertical',command=self.yview)
    self.config(yscrollcommand=self.scrollbar.set)
    
    请参见选项卡类中的如何使用它

  • 这里是tabs.py文件

    #tabs.py
    将tkinter作为tk导入
    从基架导入基架
    从customlistbox导入customlistbox
    从tkinter导入ttk,N,S,END,扩展
    类别Tab1(基架):
    “这是表1。”
    def _初始功率(自,主=无,**kw):
    超级()
    self.button2=tk.Button(self,text='Welcome to Tab1',command=self.show\u info)
    self.button2.grid(行=0,列=0)
    self.button=tk.button(self,text='Hello',command=self.say_Hello)
    self.button.grid(行=1,列=0)
    self.items=['A','B','C']
    self.listbox=CustomListbox(self,selectmode=EXTENDED,exportselection=0)
    self.listbox.grid(行=2,列