首页 > 解决方案 > 通过绑定方法使用 tkinter 条目更新字典值

问题描述

基于 Tkinter 的 GUI,应该更新字典值。它工作正常,还有两个问题:

  1. 为了更新条目值,我使用了该bind方法,即object.bind("<Key>", self._accept)它仅适用于Enter键,而其他键则打印插入条目中的前一个值 [已解决]
  2. 我不知道如何设置entry_c2=entry_c1相应的复选框何时被停用。
import tkinter as tk

def create_input_dictionary():
    out = {'Header': ['LLL', 'Min', 'Max'],
           'Do': ['l1', 'mm', '25', '35'],
           'Di': ['l2', 'mm', '19', '29'],
           'tt': ['l3', 'mm', '0.8', '1.2'],
           'y': ['l4', '-', '2', '3'],
           'eps': ['l5', 'mm', '0.1', '0.2'],
           'Header': ['LLL', 'Min', 'Max'],
           'P': ['l6', 'MPa', '3', '5'],
           'T': ['l7', '°C', '30', '50'],
           'V': ['l8', 'm/s', '3', '5'],
           'nos': ['l10', '10']
           }
    return out

def isfloat(value):
    """The function checks if an element is a number"""
    try:
        float(value)
        return True
    except ValueError:
        return False

def isinteger(value):
    """The function checks if an element is a number"""
    try:
        int(value)
        return True
    except ValueError:
        return False

def isnumber(value):
    return isfloat(value) or isinteger(value)

def allarefloats(var_list):
    """The function checks if all the elements in the lists are numbers"""
    check = True
    for item in var_list:
        check = check and isfloat(item)
    return check

def allareinteger(var_list):
    """The function checks if all the elements in the lists are numbers"""
    check = True
    for item in var_list:
        check = check and isinteger(item)
    return check

def areallnumbers(var_list):
    check = True
    for item in var_list:
        check = check and (isfloat(item) or isinteger(item))
    return check

class DictionaryEntry(tk.Frame):
    """get entry and update dictionary values"""

    def __init__(self, parent, key_dict, values_dict, row_entry, bg=None, **kwargs):
        if bg is None:
            bg = parent['bg']
        super().__init__(parent, bg=bg, **kwargs)

        self.row = row_entry
        self.key = key_dict
        self.values = values_dict
        self.nac = tk.IntVar()
        self.entry_c1 = None
        self.entry_c2 = None

        if isnumber(self.values[-1]):
            if isnumber(self.values[-2]):

                self.variable = tk.StringVar(value=self.values[-2]), tk.StringVar(self, self.values[-1])

                tk.Checkbutton(parent, variable=self.nac, command=lambda: self.naccheck()).grid(row=self.row, column=0,
                                                                                                sticky='ns')

                label = self.values[0] + ' (' + self.values[1] + ') '
                tk.Label(parent, text=label, padx=10, pady=5).grid(row=self.row, column=1, sticky='nw')

                self.entry_c1 = tk.Entry(parent, textvariable=self.variable[0], width=10, state='normal')
                self.entry_c1.grid(row=self.row, column=2)

                self.entry_c2 = tk.Entry(parent, textvariable=self.variable[1], width=10, state='disabled')
                self.entry_c2.grid(row=self.row, column=3)

            else:
                self.variable = tk.StringVar(self, value=self.values[-1])

                tk.Label(parent, text='SIMULATION PARAMETERS', padx=10, pady=5).grid(row=self.row, columnspan=4,
                                                                                     sticky='ns')
                tk.Label(parent, text=self.values[0], padx=10, pady=5).grid(row=self.row + 1, columnspan=2, sticky='ns')
                self.variable = tk.StringVar(self, self.values[-1])
                self.entry_c1 = tk.Entry(parent, textvariable=self.variable, width=10, state='normal')
                self.entry_c1.grid(row=self.row + 1, column=2, columnspan=2)

            self.entry_c1.bind("<Key>", self._accept)
            if self.entry_c2 is not None:
                self.entry_c2.bind("<Key>", self._accept)

        else:
            tk.Label(parent, text=self.values[0], padx=10, pady=5).grid(row=self.row, column=1, sticky='ns')
            tk.Label(parent, text=self.values[1], padx=10, pady=5).grid(row=self.row, column=2, sticky='ns')
            tk.Label(parent, text=self.values[2], padx=10, pady=5).grid(row=self.row, column=3, sticky='ns')

        print(self.entry_c1, self.entry_c2)

    def naccheck(self):
        if self.nac.get() == 0:
            self.entry_c2.configure(state='disabled')
        else:
            self.entry_c2.configure(state='normal')

    def _accept(self, event):  # finire!! update dictionary
        """Accept value change when return is pressed or losing focus"""
        try:
            if self.entry_c1 is not None:
                self.values[-2] = self.entry_c1.get()
            if self.entry_c2 is not None:
                self.values[-1] = self.entry_c2.get()

        except ValueError:
            pass

if __name__ == '__main__':

    dictionary = create_input_dictionary()

    root = tk.Tk()
    radio_button_frame = tk.Frame(root, padx=10, pady=5)
    input_data_frame = tk.Frame(root, padx=10, pady=5)
    simul_button_frame = tk.Frame(root, padx=10, pady=5)

    # place the container within the main window using grid
    radio_button_frame.grid(row=0, column=0, sticky='ns')
    input_data_frame.grid(row=1, column=0, sticky='ns')
    simul_button_frame.grid(row=2, column=0, sticky='ns')

    row = 0
    for key, values in dictionary.items():
        obj = DictionaryEntry(input_data_frame, key, values, row)
        dictionary.update({key: obj.values})
        row += 1
    tk.Button(simul_button_frame, text="click me", command=lambda: print(dictionary)).pack(padx=10, pady=5)

    root.update()
    root.mainloop()

编辑:第一点标记为固定

标签: pythondictionarytkintertkinter-entry

解决方案


对于第 1 项,只需绑定<KeyRelease>而不是<Key>.

entry_c1对于第 2 项,只需将内容从to复制到entry_c2禁用entry_c2inside之前naccheck()

    def naccheck(self):
        if self.nac.get() == 0:
            # copy value from entry_c1 to entry_c2
            value = self.variable[0].get()
            self.variable[1].set(value)
            # update self.values[-1] as well
            self.values[-1] = value
            # then disable entry_c2
            self.entry_c2.configure(state='disabled')
        else:
            self.entry_c2.configure(state='normal')

推荐阅读