从tkinter.Listbox中提取项目列表

7
我写了下面的tkinter脚本以了解如何将数据列表添加到tkinter.Listbox小部件中。我发现有两种方法可以实现。
接下来,我想从tkinter.Listbox小部件中提取相同的列表。在4种不同的方法中,我只成功让第4种方法(即e4)起作用。
如何让e1、e2和e3方法起作用?最终目标是获取最初提供给tkinter.Listbox小部件的相同列表。
测试脚本:
import tkinter as tk # Python 3 tkinter modules
import tkinter.ttk as ttk

class App(ttk.Frame):
    def __init__(self, parent, *args, **kwargs):
        # 1. Initialise Frame
        ttk.Frame.__init__(self, parent)
        self.parent = parent

        # Method1
        name1 = ['Peter', 'Scotty', 'Walter', 'Scott', 'Mary']
        self.lb1_values = tk.StringVar(value=name1)
        self.listbox1 = tk.Listbox(self, listvariable=self.lb1_values)

        # Method2
        self.listbox2 = tk.Listbox(self)
        name2 = ['Sarah', 'Sean', 'Mora', 'Mori', 'Mary']
        for item in name2:
            self.listbox2.insert(tk.END, item)

        self.listbox1.grid(in_=self, row=0, column=0, sticky='nsew')
        self.listbox2.grid(in_=self, row=0, column=1, sticky='nsew')

        # Extract values from listbox and covert to a list
        e1 = self.lb1_values.get()
        print('e1 = ', e1)
        print('type(e1) = ', type(e1))
        e1 = e1.strip(',')
        print('e1 = ', e1)

        e2 = self.listbox1.cget('listvariable')
        print('\ne2 = ', e2)
        print('type(e2) = ', type(e2))
        e2 = e2.split(',')
        print('e2 = ', e2)

        e3 = self.listbox2.cget('listvariable')
        print('\ne3 = ', e3)
        print('type(e3) = ', type(e3))

        e4 = self.listbox2.get(0, tk.END)
        print('\ne4 = ', e4)
        print('type(e4) = ', type(e4))
        e4 = list(e4)
        print('e4 = ', e4)    


if __name__ == '__main__':
    root = tk.Tk()
    root.title('App'), root.geometry('400x200')
    app = App(root)
    app.grid(row=0, column=0, sticky='nsew')
    #root.mainloop()

输出:

e1 =  ('Peter', 'Scotty', 'Walter', 'Scott', 'Mary')
type(e1) =  <class 'str'>
e1 =  ('Peter', 'Scotty', 'Walter', 'Scott', 'Mary')

e2 =  PY_VAR0
type(e2) =  <class 'str'>
e2 =  ['PY_VAR0']

e3 =  
type(e3) =  <class 'str'>

e4 =  ('Sarah', 'Sean', 'Mora', 'Mori', 'Mary')
type(e4) =  <class 'tuple'>
e4 =  ['Sarah', 'Sean', 'Mora', 'Mori', 'Mary']

1
@Nae 输出已被追加。 - Sun Bear
2
PY_VAR 是内部 tcl 变量的名称,因此您可以依赖 globalgetvar 函数来检索值。例如:print(list(self.tk.globalgetvar(self.listbox1.cget('listvariable')))) - CommonSense
@Sun Bear,get 的结果实际上是 globalgetvar 函数转换为 str,因此请考虑覆盖此函数。 - CommonSense
1
@Nae 我使用了 StringVar,因为 New Mexico Techtk.Listbox 小部件的 listvariable 选项中教授了这种方法。tk.Listbox 确实可以获取这些值。我希望我已经正确理解了你的问题和 New Mexico Tech 的指示。我刚刚发现了 tk.Variable 的存在以及它与 tk.StringVar 的区别。 - Sun Bear
@SunBear 我也不建议这样做。使用tk.Variable(在Bryan的回答中提出)可能是最好的选择,因为Bryan Oakley是该主题上最资深的程序员之一,如果不是最资深的话(至少我知道的是这样)。 - Nae
显示剩余5条评论
1个回答

7

您不能将StringVar用作listvariable属性的目标。根据您的代码,这会导致列表被转换为字符串。

但是,您可以使用tk.Variable的实例。 VariableStringVar的基类。 get方法的基本实现不会将值强制转换为字符串。

name1 = ['Peter', 'Scotty', 'Walter', 'Scott', 'Mary']
self.lb1_values = tk.Variable(value=name1)
self.listbox1 = tk.Listbox(self, listvariable=self.lb1_values)
...
e1 = self.lb1_values.get()
print('e1 = ', e1)
print('type(e1) = ', type(e1))
print('e1 = ', e1)

上述代码会产生以下输出:
e1 =  ('Peter', 'Scotty', 'Walter', 'Scott', 'Mary')
type(e1) =  <class 'tuple'>
e1 =  ('Peter', 'Scotty', 'Walter', 'Scott', 'Mary')

对于 e2 和 e3,你需要多做一些工作。不幸的是,cget 方法返回的是内部变量名称,而不是变量对象的引用。要通过名称获取变量的值,需要使用 widget 方法 getvar

例如:

e2 = self.listbox1.cget('listvariable')
print('\ne2 = ', e2)
print('type(e2) = ', type(e2))
print('e2 = ', self.getvar(e2))

以上代码将产生以下输出:
e2 =  PY_VAR0
type(e2) =  <class 'str'>
e2 =  ('Peter', 'Scotty', 'Walter', 'Scott', 'Mary')

感谢您的解释。我之前使用StringVar是因为在Listbox小部件的listvariable中教授了这种方法。但是,我无法按照您的说明使e3正常工作。出现了File "/usr/lib/python3.5/tkinter/__init__.py", line 507, in getvar return self.tk.getvar(name) _tkinter.TclError: can't read "": no such variable的错误。难道在通过Method 2向listbox提供数据时,我不能使用.cget('listvariable')吗? - Sun Bear
1
@SunBear e3 无法工作的原因是 self.listbox2 没有一个 listvariable,它具有默认值 ""。当您尝试使用 getvar 时,它会尝试搜索一个不存在的对象。 - Nae
1
@Nae:是的,谢谢你注意到了。 - Bryan Oakley
1
我说self.listbox2没有listvariable是正确的吗?因为Method2没有使用listvariable来将数据加载到tk.Listbox中,而是使用.insert(tk.END, item)方法。如果是这样,这意味着tk.Listbox有两种存储数据的方法。在@Nae的问题中,我了解到listvariable是一个变量类。那么通过.insert(tk.END, item)方法存储数据所使用的对象类型是什么?我认为它不是一个变量类,因为getvar返回"" - Sun Bear
1
@SunBear:数据只是由小部件内部存储。列表框本身是保存数据的对象。 - Bryan Oakley
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接