简体   繁体   中英

TreeView Selection Handler triggering twice

I am trying to display a Tree of objects in PyGTK such that when you click on one object, it will move to the previous space and then render its children where it was.

For example, if we start with object 1 selected, its children will be displayed.

| Level 1      | Level 2          |
| ->Object 1<- | Object 1 Child 1 |  
| Object 2     | Object 1 Child 2 |  
| Object 3     | Object 1 Child 3 |   

If we then select one of its children, its children will get displayed.

| Level 1              | Level 2                  |
| ->Object 1 Child 1<- | Object 1 Child 1 Child 1 |  
| Object 1 Child 2     | Object 1 Child 1 Child 2 |  
| Object 1 Child 3     | Object 1 Child 1 Child 3 |

So we are just traversing through the tree of data. I have implemented this with PyGTK.TreeView 's connected to PyGTK.ListStore 's that hold the display value of the object, and then another list of the actual objects themselves.
I have methods to listen for the PyGTK.TreeViewSelection changed event to do the re-rendering of the data.
The problem is, when I am rebuilding the ListStore 's, for the new object, the event is getting hit twice, and I can't figure out why.
Simply eating the first or second event doesn't seem to work because occasionally only one event is fired.

Below is some working sample code illustrating what is happening and kind of what I am trying to do:

#!/usr/bin/python3

import gi
gi.require_version('Gtk','3.0')
gi.require_version('WebKit2','4.0')
from gi.repository import Gtk, WebKit2, Gdk

class TmpWindow(Gtk.Window):
   def __init__(self):
      Gtk.Window.__init__(self)


      self.set_position(Gtk.WindowPosition.CENTER)
      self.connect('delete-event', Gtk.main_quit)

      self.outerBox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL,spacing=6)
      self.add(self.outerBox)

      self.urlGrid = Gtk.Grid()
      self.urlGrid.set_column_homogeneous(True)
      self.urlGrid.set_row_homogeneous(True)
      self.outerBox.pack_start(self.urlGrid,False,False,10)

      # Set the starting lists
      self.node0List = ['Object']
      self.node0GridList = Gtk.ListStore(str)
      self.node0GridList.append(['ObjectString'])

      self.node1List = ['Object2', 'Object3']
      self.node1GridList = Gtk.ListStore(str)
      [self.node1GridList.append([child]) for child in self.node1List]


      self.treeView0 = Gtk.TreeView.new_with_model(self.node0GridList)
      renderer = Gtk.CellRendererText()
      column = Gtk.TreeViewColumn('Node0',renderer, text=0)
      self.treeView0.append_column(column)
      self.scrollable_treelist0 = Gtk.ScrolledWindow()
      self.scrollable_treelist0.add(self.treeView0)
      self.urlGrid.attach(self.scrollable_treelist0, 0 ,0,200,10)

      self.treeView1 = Gtk.TreeView.new_with_model(self.node1GridList)
      renderer = Gtk.CellRendererText()
      column = Gtk.TreeViewColumn('Node1',renderer, text=0)
      self.treeView1.append_column(column)
      self.scrollable_treelist1 = Gtk.ScrolledWindow()
      self.scrollable_treelist1.add(self.treeView1)
      self.urlGrid.attach_next_to(self.scrollable_treelist1,self.scrollable_treelist0,Gtk.PositionType.RIGHT, 200,10)


      self.treeView0SignalId = self.treeView0.get_selection().connect('changed',self.node0Selection)
      self.treeView1SignalId = self.treeView1.get_selection().connect('changed',self.node1Selection)
      self.show_all()

   def node0Selection(self, selection):
      print('Hitting Node0 Selection Handler')
      self.treeView0.get_selection().handler_block(self.treeView0SignalId)
      self.treeView1.get_selection().handler_block(self.treeView1SignalId)

      tmp = self.node0List
      self.node0List = self.node1List
      self.node1List = tmp

      self.node0GridList.clear()
      [self.node0GridList.append([child]) for child in self.node0List]

      self.node1GridList.clear()
      [self.node1GridList.append([child]) for child in self.node1List]

      self.treeView0.get_selection().handler_unblock(self.treeView0SignalId)
      self.treeView1.get_selection().handler_unblock(self.treeView1SignalId)

   def node1Selection(self, selection):
      print('Hitting Node1 Selection Handler')
      self.treeView0.get_selection().handler_block(self.treeView0SignalId)
      self.treeView1.get_selection().handler_block(self.treeView1SignalId)

      tmp = self.node0List
      self.node0List = self.node1List
      self.node1List = tmp

      self.node0GridList.clear()
      [self.node0GridList.append([child]) for child in self.node0List]

      self.node1GridList.clear()
      [self.node1GridList.append([child]) for child in self.node1List]

      self.treeView0.get_selection().handler_unblock(self.treeView0SignalId)
      self.treeView1.get_selection().handler_unblock(self.treeView1SignalId)

if __name__ == '__main__':
   TmpWindow()
   Gtk.main()

Clicking on any of the items in the list should display a message in the console when the handler is hit. Notice that they are getting hit twice in a row with a single mouse click.

I ended up working around this by putting my on-click handlers on the tree_view row-activated events. instead of selection changed events.

self.tree_views[0].connect('row-activated',self.node_one_selection)

I'll still accept an answer for why I have to do that (curious what my flaw in thinking about GTK widgets is/was).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM