2017-07-10 210 views
1

我在tkinter中使用python 3樹形視圖。 問題是,當我綁定右鍵單擊以獲取右鍵單擊行的行ID時,我最終得到上一個事件的實際行ID。例如,我可以右鍵單擊「項目1」,這會返回我「」,然後右鍵單擊「項目2」,並以rowID的形式返回「項目1」。Tkinter Treeview識別右鍵單擊事件返回以前右鍵單擊的行

def initTreeView(self): 
    self.treeView = ttk.Treeview(self.treeSectionFrame) 
    self.treeView.heading('#0', text='Projects') 

    self.treeView.grid(row=0, column=0, sticky=("N", "S", "E", "W"))    


    self.treeView.bind('<3>', self.rightClickMenu) 

def rightClickMenu(self, event): 
    def hello(): 
     print("hello!") 
    # create a popup menu 
    print(event.x, event.y) 
    rowID = self.treeView.identify('item', event.x, event.y) 
    if rowID: 
     menu = Menu(self.root, tearoff=0) 
     menu.add_command(label="Undo", command=hello) 
     menu.add_command(label="Redo", command=hello) 
     menu.post(event.x_root, event.y_root) 

     self.treeView.selection_set(rowID) 
     self.treeView.focus_set() 
     self.treeView.focus(rowID) 
     print(rowID) 
    else: 
     pass 

感謝,

[編輯]

我發現一個骯髒的黑客其中包括使每一個項目相同,其ID的標籤,以便您可以再提取實際的ROWID的。這也可以使用值選項完成。

self.treeView.insert("", "end", "id-1, tags="id-1", text="Project 1") 

... 
rowID = self.treeView.identify('item', event.x, event.y) 
rowID = self.treeView.item(rowID)["tags"] # gives you actual ID 

回答

0

首先,如果你要打印的實際rowID,那麼就打印出來馬上:

... 
rowID = self.treeView.identify('item', event.x, event.y) 
print(rowID) 
... 

...但當然,這是不是你從什麼期待代碼。爲了克服這個問題 - 讓我們顛倒邏輯一點點:

def rightClickMenu(self, event): 
    def hello(): 
     print("hello!") 
    # create a popup menu 
    print(event.x, event.y) 
    rowID = self.treeView.identify('item', event.x, event.y) 
    if rowID: 
     self.treeView.selection_set(rowID) 
     self.treeView.focus_set() 
     self.treeView.focus(rowID) 
     print(rowID) 

     menu = Menu(self.root, tearoff=0) 
     menu.add_command(label="Undo", command=hello) 
     menu.add_command(label="Redo", command=hello) 
     menu.post(event.x_root, event.y_root) 
    else: 
     pass 

正如你所看到的,現在改變選擇不阻止的Menu部件。

其原因是因爲post方法顯示Menu馬上,這個事件需要以某種方式處理tk。因此,我們有一個主要問題:那個post的定位。

另一種方法例如:

... 
    menu = Menu(self.root, tearoff=0) 
    menu.add_command(label="Undo", command=hello) 
    menu.add_command(label="Redo", command=hello) 

    self.treeView.selection_set(rowID) 
    self.treeView.focus_set() 
    self.treeView.focus(rowID) 
    print(rowID) 
    menu.post(event.x_root, event.y_root) 
    ... 

但在我看來,我覺得這裏最邏輯上正確的選項是選擇提取處理到另一個功能,並把它作爲一個Menu參數postcommand。因此,在此之後,您不會同時使用一個回調函數坐在兩把椅子上。

+0

謝謝,現在完美。如何反轉它使它工作? –

+0

@我是Legend,因爲在事件隊列中存在某種重疊(我假設),它看起來像'tkinter'返回到主循環,因爲用戶可以與菜單交互,並且在菜單可見時阻止代碼執行。無論如何,我略微更新了我的答案。 – CommonSense