首页 > 解决方案 > 如何检测 Tkinter 中单击的按钮在哪一帧上?

问题描述

我有个问题。我有这个代码:

import tkinter as tk

class new_f:
    def __init__(self,root,num):
        self.new_frame=tk.Frame(root,width=100,height=100,bg='white',bd=3,relief=tk.GROOVE)
        self.new_frame.pack(side=tk.LEFT,fill=tk.X,expand=True)

        self.num=num

    def add_label(self,t):
        self.l1=tk.Label(self.new_frame,bg='white',text=t)
        self.l1.pack()

    def return_instance(self):
        return self.num

class Main_win:
    def __init__(self,root):
        self.root=root
        self.bind_number=0
        self.current_index=0

        self.instance_list=[]

        self.b1=tk.Button(self.root,text='Add Frame',command=self.add_frame_win)
        self.b1.pack(side=tk.BOTTOM)

        self.b2=tk.Button(self.root,text='Add text',command=self.add_text_frame)
        self.b2.pack(side=tk.BOTTOM)

    def return_instance_num(self,num,*args):
        self.current_index=num

    def add_frame_win(self):
        new_in=new_f(self.root,self.bind_number)
        self.instance_list.append(new_in)

        new_in.new_frame.bind('<Button-1>',lambda evnt: self.return_instance_num(new_in.return_instance()))
        #self.current_index=new_in.return_instance()
        self.bind_number+=1

    def add_text_frame(self):
        instance=self.instance_list[self.current_index]
        instance.add_label('Hello World')

root=tk.Tk()
ob=Main_win(root)
root.mainloop()

我试图实现的是我想检测在哪个框架上单击了鼠标左键,以便使该框架处于活动状态并将标签添加到该特定框架。

但是,我被困在如何编写代码上。我需要一个新课程因为我不知道用户需要多少帧。

这是我稍后将要实现的代码的一个简短示例。所以我的问题是:

标签: pythontkinter

解决方案


在这种方法中,我有标签l1绑定到Button-1

这是通过传递selfnew_f而不是root 和绑定self.l1来实现的Button-1

import tkinter as tk

class new_f:
    def __init__(self, prog, num):
        self.prog = prog
        self.new_frame = tk.Frame(prog.root, width = 100, height = 100, bg = 'white', bd = 3, relief = tk.GROOVE)
        self.new_frame.pack(side = tk.LEFT, fill = tk.X, expand = True)

        self.num = num

    def add_label(self, t):
        self.l1 = tk.Label(self.new_frame, bg = 'white', text = t)
        self.l1.pack()
        # binding button-1 press to label
        self.l1.bind("<Button-1>", lambda evnt: self.prog.return_instance_num(self.return_instance()))

    def return_instance(self):
        return self.num

class Main_win:
    def __init__(self, root):
        self.root = root
        self.bind_number = 0
        self.current_index = 0

        self.instance_list = []

        self.b1 = tk.Button(self.root, text = 'Add Frame', command = self.add_frame_win)
        self.b1.pack(side = tk.BOTTOM)

        self.b2 = tk.Button(self.root, text = 'Add text', command = self.add_text_frame)
        self.b2.pack(side = tk.BOTTOM)

    def return_instance_num(self, num, *args):
        self.current_index = num

    def add_frame_win(self):
        # note passing self not root
        new_in = new_f(self, self.bind_number)
        self.instance_list.append(new_in)

        new_in.new_frame.bind('<Button-1>', lambda evnt: self.return_instance_num(new_in.return_instance()))
        #self.current_index = new_in.return_instance()
        self.bind_number = self.bind_number + 1

    def add_text_frame(self):
        instance = self.instance_list[self.current_index]
        instance.add_label('Hello World')

root = tk.Tk()
ob = Main_win(root)
# This necessary to prevent error if user hits 'Add text' before 'Add Frame'
ob.add_frame_win()
root.mainloop()

这是另一种方法,它使用字典来存储对象作为键和l1实例作为值。new_framenew_f

此方法可用于其他tkinter对象(条目、列表框、文本、画布)

import tkinter as tk

class new_f:
    def __init__(self, parent):
        self.parent = parent
        self.frame = tk.Frame(
            parent.root, width = 100, height = 100,
            bg = "white", bd = 3, relief = tk.GROOVE)
        self.frame.pack(
            side = tk.LEFT, fill = tk.X, expand = True)
        self.frame.bind("<Button-1>", parent.get_current_frame)

    def add_label(self, t):
        self.label = tk.Label(self.frame, bg = "white", text = t)
        self.label.pack(fill = tk.BOTH, expand = True)
        # bind button-1 to label, set instance_label and current to self
        self.label.bind("<Button-1>", self.parent.get_current_label)
        self.parent.instance_label[self.label] = self.parent.current = self

class Main_win:

    instance_label = dict() # This method can be expanded for other objects
    instance_frame = dict() # that you may want to create in frames
    
    def __init__(self, root):
        self.root = root
        self.b1 = tk.Button(
            self.root, text = "Add Frame", command = self.add_frame_win)
        self.b1.pack(side = tk.BOTTOM)
        self.b2 = tk.Button(
            self.root, text = "Add text", command = self.add_text_frame)
        self.b2.pack(side = tk.BOTTOM)

    def get_current_label(self, ev):
        self.current = self.instance_label[ev.widget]

    def get_current_frame(self, ev):
        self.current = self.instance_frame[ev.widget]

    def add_frame_win(self):
        # note passing self not root
        self.new_in = new_f(self)
        self.instance_frame[self.new_in.frame] = self.current = self.new_in

    def add_text_frame(self):
        # Change message with entry tool?
        self.current.add_label("Hello World")

root = tk.Tk()
ob = Main_win(root)
# This necessary to prevent error if user hits 'Add text' before 'Add Frame'
ob.add_frame_win()
root.mainloop()

推荐阅读