从 tkinter.Listbox 中提取项目列表

Posted

技术标签:

【中文标题】从 tkinter.Listbox 中提取项目列表【英文标题】:Extracting a list of items from tkinter.Listbox 【发布时间】:2018-07-15 01:53:19 【问题描述】:

我编写了以下 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']

【问题讨论】:

我现在是 AFpK。您能否提供print('type(e... 表达式的结果? @Nae 输出已附加。 PY_VAR 是内部 tcl 变量的名称,因此您可以依靠 globalgetvar 函数来检索值。例如:print(list(self.tk.globalgetvar(self.listbox1.cget('listvariable')))). @CommonSense 谢谢。让它为e2工作。你知道如何解决e1吗?必须有非常确定和简单的方法将 e1 返回的字符串转换为列表。 @Nae 我曾经使用过StringVar,因为New Mexico Tech 教过tk.Listbox 小部件的listvariable 选项。 tk.Listbox 确实得到了这些值。我希望我已经正确理解了您的问题和新墨西哥技术说明。我只是发现tk.Variable 的存在,它与tk.StringVar 不同。 【参考方案1】:

您不能使用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 方法返回的是内部变量名,而不是对变量对象的引用。要通过名称获取变量的值,您需要使用小部件方法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。通过方法2向列表框提供数据时我不能使用.cget('listvariable')吗? @SunBear e3 不起作用的原因是self.listbox2 没有 listvariable,因为它的默认值为""。当您尝试使用getvar 时,它会尝试搜索一个不是的对象。 @Nae:是的。感谢您的关注。 我是否正确地说 self.listbox2 没有 listvariable 因为 Method2 不使用 listvariable' to load data into a tk.Listbox` 而是使用 .insert(tk.END, item) 方法?如果是这样,这意味着 tk.Listbox 有 2 种存储数据的方法。在@Nae 的问题中,我收集到listvariable 是一个变量类。那么通过.insert(tk.END, item) 方法使用什么类型的对象来存储数据呢?我认为它不是一个变量类,因为getvar 返回"" @SunBear:数据只是由小部件内部存储。列表框本身就是保存数据的对象。

以上是关于从 tkinter.Listbox 中提取项目列表的主要内容,如果未能解决你的问题,请参考以下文章

Python中tkinter中控件的使用(6.Listbox列表框(单击多选))

如何在 Tkinter 列表框中插入时添加自动滚动?

Tkinter Listbox 以蓝色突出显示一个元素,但在另一个元素周围放置黑色边框?

如何清除 Tkinter ListBox Python

调整窗口大小时调整 Tkinter Listbox 小部件的大小

如何使单个 Tkinter Listbox 元素出现换行符?