【问题标题】:Python / Tkinter listbox troublesPython / Tkinter 列表框问题
【发布时间】:2013-01-07 05:35:34
【问题描述】:

我发布了一个问题here,并建议我重组代码。现在已经不同了,我觉得有理由提出一个新问题。

无论如何,我正在尝试将拖放功能添加到列表框,但我认为最好的第一步是让事件绑定首先工作。目前,当我单击列表时,单击列表框时出现以下错误。出现列表框窗口,但是当我单击它时会发生错误。

 "AttributeError: make_list instance has no attribute 'nearest'.

此外,当我在 build_listbox 方法中打印列表框时,会打印以下小数点 .40720520L。这不应该打印列表框中的值吗?毕竟,方法相同。列表框是否未正确创建?

from Tkinter import *
import Tkinter

class make_list:

    def move_mouse(self, event):
        self.curIndex = event.nearest(event.y)
        print self.curIndex

    def click_button(self, event):
        w= event.widget
        self.curIndex = int(w.curselection()[0])
        #print self.curIndex
        value = w.get(self.curIndex)
        print value

    def build_main_window(self):
        self.build_listbox()

    def build_listbox(self):
        listbox = Listbox()
        listbox.bind('<<ListboxSelect>>', self.click_button)
        listbox.bind('<B1-Motion>', self.move_mouse)
        for item in ["one", "two", "three", "four"]:
            listbox.insert(END, item)    
        listbox.insert(END, "a list entry")
        listbox.pack()
        print listbox
        return

if __name__ == '__main__':
    start = make_list()
    start.build_main_window()
    mainloop()

【问题讨论】:

  • 您能否发布完整的回溯,以便我们知道是哪一行产生了异常?
  • 实际上你在move_mouse() 定义的第一行得到了一个AttributeError: Event instance has no attribute 'nearest'。那是因为event 对象没有nearest 方法函数属性。
  • 顺便说一句,PEP 8 的类命名约定是 CapCase 所以 make_list 应该是 MakeList。
  • ListBox 对象有一个 curselection() 方法,它返回您应该使用的所选元素的行号。我建议您花一些时间阅读网络上和各种书籍中存在的众多 Tkinter tutorials 之一。
  • 对不起,我的错误。 listvariable 是小部件选项而不是属性,因此检索其当前值是使用 listbox.cget('listvariable') 完成的——但是,由于未知原因,它返回一个空字符串。起作用的是listbox.get(0, END),它返回元组('one', 'two', 'three', 'four', 'a list entry')。顺便说一句,在build_listbox() 中创建的ListBox 实例存储在局部变量listbox 中,并且会在函数返回时自动删除——所以我建议您改为(或也)将值分配给self.listbox 以防止这不会发生。

标签: python events listbox widget tkinter


【解决方案1】:

当您在 Tkinter 小部件上执行 print 时获得的值在很大程度上与用户无关,它只是为您创建的 Tcl 变量的名称。

现在,由于您的代码显然正在运行(通过快速浏览问题中的 cmets),我建议以不同的方式执行拖放功能。例如,如果我们有一个与Listbox 中的值相关联的值列表,那么如果我们可以更新这个列表,然后它会反映在Listbox 显示上,那么执行任务会容易得多,正确的 ?太糟糕了,我们在 Python 中没有这样的东西,但目前考虑以下代码:

import Tkinter

def list_click(event):
    w = event.widget
    index = w.nearest(event.y)
    w._selection = index

def list_motion(event):
    w = event.widget
    if w._selection is None:
        return
    index = w.curselection()[0]
    w._var.swap(index, w._selection)
    w._selection = index

def list_clear(event):
    event.widget._selection = None

root = Tkinter.Tk()

v = ListVar(values=('one', 'two', 'three', 'four'))
v.append('a list entry')

listbox = Tkinter.Listbox(listvar=v)
listbox.pack()

listbox._selection = None
listbox._var = v
listbox.bind('<1>', list_click)
listbox.bind('<B1-Motion>', list_motion)
listbox.bind('<ButtonRelease-1>', list_clear)

root.mainloop()

此代码的工作方式如下:当在列表框中单击鼠标时,它将最近的项目标记为“选中”,当您移动鼠标时,它交换项目并更新选择,当您释放鼠标按钮时,它清除选择。那么缺少的是ListVar 的东西。这里是:

class ListVar(Tkinter.Variable):
    def __init__(self, master=None, name=None, **kwargs):
        Tkinter.Variable.__init__(self, master, kwargs.get('values'), name)

    def set(self, values):
        self._tk.call('set', self._name, values)

    def set_index(self, index, value):
        self._tk.call('lset', self._name, index, value)

    def get_index(self, index):
        return self._tk.eval('lindex $%s %d' % (self._name, index))

    def get(self, start=None, end=None):
        if start is None and end is None:
            res = self._tk.eval('lrange $%s 0 end' % self._name)
        elif end is None:
            res = self._tk.eval('lrange $%s %d end' % (self._name, start))
        else:
            res = self._tk.eval('lrange $%s %d %d' % (self._name, start, end))
        return self._tk.splitlist(res)

    def swap(self, a, b):
        if a != b:
            tmp = self.get_index(a)
            self.set_index(a, self.get_index(b))
            self.set_index(b, tmp)

    def append(self, value):
        self._tk.eval('lappend %s {%s}' % (self._name, value))

它很粗糙,如果你传递一个像“hello{”之类的值会失败。这可以在很多方面进行改进。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-30
    • 2018-01-08
    相关资源
    最近更新 更多