简体   繁体   English

Python、Tkinter:可以在不使用全局变量或定义新类的情况下在按钮回调中修改列表吗?

[英]Python, Tkinter: Can a list be modified within a button callback without using global variables or defining new classes?

Ideally, I would like to use a built-in approach like tk.StringVar to modify a list (of strings) in a button command, but also need the modified list to live on so it can be modified in additional function calls.理想情况下,我想使用像tk.StringVar这样的内置方法来修改按钮命令中的(字符串)列表,但还需要修改后的列表继续存在,以便可以在额外的 function 调用中对其进行修改。 The line print(a) in the code below prints a list-like object ('abc', 'gh', 'rstu') , but the line print(a[1]) fails to return gh and the line a.append('xyz') returns an error (included further below), suggesting that I can't directly hijack tk.StringVar to carry the list.下面代码中的print(a)行打印了一个类似列表的 object ('abc', 'gh', 'rstu') ,但是print(a[1])行无法返回gh并且a.append('xyz')a.append('xyz')返回一个错误(包括在下面),表明我不能直接劫持tk.StringVar来携带列表。 What is then my best option, if I should avoid the perils of making the list global and the overhead of defining a class?如果我应该避免使列表全局化的危险和定义 class 的开销,那么我最好的选择是什么?

import tkinter as tk

def append():
    a = a_var.get()
    print(a)
    print(a[1])
    a.append('xyz')
    a_var.set(a)

a_arr = ['abc','gh','rstu']
print(a_arr)

window = tk.Tk()
a_var = tk.StringVar()
a_var.set(a_arr)

tk.Button(window, text='Append', command=append).pack()

window.mainloop()

For completeness, the output and error returned by the above code is为完整起见,上述代码返回的 output 和错误为

['abc', 'gh', 'rstu']
('abc', 'gh', 'rstu')
'
Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\...\Python39\lib\tkinter\__init__.py", line 1884, in __call__
    return self.func(*args)
  File "c:\Users\...\TestAppend.py", line 7, in modify
    a.append('xyz')
AttributeError: 'str' object has no attribute 'append'

If your goal is to append to a_arr , you can pass it into the callback using lambda .如果您的目标是将 append 传递给a_arr ,则可以使用lambda将其传递给回调。 There's no need for the callback to return anything since you will be modifying the object rather than replacing it with a new object.回调不需要返回任何内容,因为您将修改 object,而不是用新的 object 替换它。

If you made the following modifications to your code, you'll see that each time you click the button, the array grows by one.如果您对代码进行了以下修改,您会看到每次单击按钮时,数组都会增长 1。

def append(a):
    a.append('xyz')
    print("a:", a)
...
tk.Button(window, text='Append', command=lambda: append(a_arr)).pack()

Of course, since a_arr is already a global variable, you can also just directly modify it当然,既然a_arr已经是全局变量,你也可以直接修改

def append():
    a_arr.append('xyz')
...
tk.Button(window, text='Append', command=append).pack()

If you want to work with list then do convert it to StringVar如果您想使用列表,请将其转换为StringVar

import tkinter as tk

def append():
    print(a_arr)
    print(a_arr[1])
    a_arr.append('xyz')

a_arr = ['abc','gh','rstu']

window = tk.Tk()
tk.Button(window, text='Append', command=append).pack()

window.mainloop()

Button runs assigned function without arguments - but you could use lambda to change it and send array as argument.按钮在没有 arguments 的情况下运行分配的 function - 但您可以使用lambda更改它并将数组作为参数发送。 But button also doesn't know what to do with returned value so you can't send back new array in return - and here you have to use global variable.但是按钮也不知道如何处理返回值,因此您无法返回新数组作为return - 在这里您必须使用全局变量。 When you write all GUI as classes then you can use self.当您将所有 GUI 编写为类时,您可以使用self. and then it is not so bad.然后还不错。

import tkinter as tk

class App():

    def __init__(self):

        self.a_arr = ['abc','gh','rstu']

        self.window = tk.Tk()
        tk.Button(self.window, text='Append', command=self.append).pack()

        self.window.mainloop()    

    def append(self):
        print(self.a_arr)
        print(self.a_arr[1])
        self.a_arr.append('xyz')

App()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM