2013-01-23 74 views
2

我發佈了一個問題here,我被建議重構代碼。現在已經不同了,我覺得有必要提出一個新的問題。Python/Tkinter列表框麻煩

無論如何,我想添加拖放功能的列表框,但我想好的第一步將是事件綁定工作在第一位。目前,當我點擊列表時,單擊列表框後出現以下錯誤。列表框窗口出現,但是當我點擊它時發生錯誤。

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

另外,當我在build_listbox方法中打印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() 
+0

你可以發佈完整的回溯,以便我們知道哪一行產生異常? – mgilson

+0

實際上,你在'move_mouse()'定義的第一行得到一個AttributeError:Event實例沒有'nearest'的屬性。這是因爲'event'對象沒有'nearest'方法函數屬性。 – martineau

+0

@martineau,我該如何改變?我很抱歉,我對tkinter和python一般都很陌生 – user1104854

回答

0

當你在一個Tkinter的部件做print你的價值在很大程度上是與用戶無關,它僅僅是爲您創建一個Tcl變量的名稱。

現在,由於顯然你的代碼正在工作(通過快速瀏覽問題中的註釋),我建議以不同的方式拖動功能&。例如,如果我們有一個與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)) 

這是非常粗糙的,如果你傳似「你好{」等,這可以在許多方面提高值將失敗。