【问题标题】:Getting a specific instance of a Tkinter label created using a FOR LOOP获取使用 FOR 循环创建的 Tkinter 标签的特定实例
【发布时间】:2023-01-27 08:54:03
【问题描述】:

我是编程的新手,之前也从未在此论坛上发帖,所以如果我的问题不清楚或者我没有使用正确的术语,我会提前道歉,但我真的很感激一些帮助。

我使用 Python 3.7.0 和 Tkinter 创建了一个简单的飞行员日志程序。 已编辑部分个人信息的屏幕截图: Log book screenshot

我已经使用显式语句(如下所示的示例代码)创建并打包了标题框架。

接下来我有一个“数据”框架,我在其中循环遍历字典。对于字典中的每个项目,我将一行新数据打包到数据框中(示例代码如下所示)。

我遇到的问题是,当我单击数据框中的一行(以允许编辑该行)时,我想调用回调函数。但是,无论我单击哪一行,我似乎只能得到打包到框架中的字典中的最后一项。

有什么方法可以调用打包的帧的特定实例而不是最终帧?

示例显式标题框架代码:

        # Heading Frame:
        self.heading_year_frame = tk.Frame(self.headingframe)
        self.heading_year_entry = tk.Label(self.heading_year_frame, width=self.entrywidth, text="YEAR", anchor='sw', font = self.fontsize, bd = 1, relief = "flat")
        self.heading_year_entry.pack(side='left', fill='y')
        heading_frames.append(self.heading_year_frame)
...
        self.heading_details_frame = tk.Frame(self.headingframe)
        self.heading_details_entry = tk.Label(self.heading_details_frame, width=self.bigentrywidth*2, text="DETAILS", anchor='sw', font = self.fontsize, bd = 1, relief = "flat")
        self.heading_details_entry.pack(side='left', fill='y')
        heading_frames.append(self.heading_details_frame)
 
...
        # Pack the heading frames
        for f in heading_frames:
            f.pack(side='left', fill='both')

使用 FOR 循环和字典生成的示例帧:

    def pack_entry(self):
        self.dataframe_regen = tk.Frame(self.dataframe)
        self.dataframe_regen.pack(side='top', fill='both')
        for i in self.flight_list[self.m:self.n]:
            self.i = self.flight_data[i]
            self.entry_year = (self.flight_data[i]["year"])
.....
            self.entry_details = (self.flight_data[i]["details"])
.....
            self.entry_year_frame = tk.Frame(self.subdataframe)
            self.entry_year_entry = tk.Label(self.entry_year_frame, width=self.entrywidth, text= self.entry_year, font = self.fontsize, anchor = 'w', bd =1, relief = 'flat')
            self.entry_year_entry.pack(side='left', fill = 'both', expand = True)
            self.sub_data_frames.append(self.entry_year_frame)
....
            self.entry_details_frame = tk.Frame(self.subdataframe)
            self.entry_details_entry = tk.Label(self.entry_details_frame, width=self.bigentrywidth*2, text= self.entry_details, font = self.fontsize, anchor = 'w', bd = 1, relief = "flat", cursor = "hand2")
            self.entry_details_entry.pack(side='left', fill='x')
            self.entry_details_entry.bind("<Button-1>", lambda e:self.popup_showinfo())
            self.sub_data_frames.append(self.entry_details_frame)

【问题讨论】:

    标签: python tkinter


    【解决方案1】:

    执行此操作有多种策略,但这取决于您希望如何访问和更改行。

    但是,在下面的任何情况下,您的回调必须以某种方式知道它正在更改哪一行。你可以做的几件事

    1. 就像在标签中所做的那样使用 lambda,并将行标识信息(无论它是什么)传递到内部函数。

    2. 使用 functools.partial 这样您就可以编写一个函数并为每一行创建部分,例如

      def edit_row(event, row_identifying_object=None):
          # use row_identifying_object to find the correct row or make any 
          # changes you want to the row_identifying_object directly
      
      for irow in range(n_rows):
          # row_obj = some object, number, string to identify row
          lbl = tk.Label()
          # this will create a new partial object that will call your 
          # function above with the row_identifying_object pre-defined 
          # to whatever row_obj is and bind it to the callback
          lbl.bind('<button-1>', functools.partial(edit_row, row_identifying_object = row_obj)) 
          
      

      至于row_obj是什么,可能是

      - 指向跟踪行的其他结构的标识符。这可能是一个丑陋的解决方案,因为程序现在需要跟踪并将此 id 链接到行内容的管理方式。

      -我见过的更常见的可能是定义一个“行”对象本身来跟踪其身份或其所有子对象。该对象本身可以是 tk.Frame,例如

      class Row():
          def __init__(self, master, *args, **kwargs):
              self.frame = tk.Frame(*args, **kwargs)
              # instantiate your elements in each row here
      
          def getter(self, element_id):
              # retrieve elements in row by some id
      
          def setter(self, element_id, *args, **kwargs):
              # make changes to elements in the row
      

      我见过的很多答案和我实际使用过的都是Row继承自tk.Frame,但是你必须小心将行元素存储在Row对象本身中。由于每个 tkinter 小部件都存储对其 master 的引用,这可能导致循环引用,从而导致内存泄漏或速度减慢......我认为 python 已经变得非常健壮,可以防止循环引用引起的内存泄漏,但仍然有很多关于创建它们的警告。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-22
      • 1970-01-01
      • 2018-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多