Syntax for TreeWidget itemDoubleClicked signal?



  • PySide and/or PyQt4 / Python 3 / Windows 7

    Hello,

    I have a Tree Widget (called self.tree) with several items added. After adding the items, I have the following line:

    @self.tree.itemDoubleClicked.connect(self.AddToTreeHere)@

    (and later in that class there is the following function:)

    @def AddToTreeHere(self):
    print('Item has been double-clicked')@

    The double-click does not seem to be emitting a signal (nothing prints when I double-click).

    Did I format the syntax incorrectly? If not, what did I do wrong?
    If the syntax is correct, what are some trouble-shooting steps I can take to find the source of the problem? (In terms of where the signal line is located in the code, etc?) I tried routing a buttonclick to the same function and it also didn't seem to emit a signal -- I'm guessing I made some rookie mistake.

    I can post the entire code if you need more information.

    Thanks



  • The following works for me (PyQt4, Py2.7, OSX ML), see if it does for you. If it does, post your code so we can take a look at the differences. Otherwise it might be an installation/config issue.

    @
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *

    class Widget(QTreeWidget):
    def init(self, parent=None):
    QTreeWidget.init(self, parent)

        self.insertTopLevelItems(0, [QTreeWidgetItem(self, ["Item %d" % i]) for i in range(3)])
        self.itemDoubleClicked.connect(self.addToTreeHere)
    
    def addToTreeHere(self):
        print "Item has been double clicked..."
    

    if name=="main":
    from sys import argv, exit
    a=QApplication(argv)
    w=Widget()
    w.show()
    w.raise_()
    exit(a.exec_())
    @



  • Thank you, this seemed to do the trick. I think this was my problem:

    I had created my tree widget within the init of my mainwindow, and my signal code was in there as well -- basically like this:

    @self.tree = QtGui.QTreeWidget()
    [[added some items]]
    self.tree.itemDoubleClicked.connect(self.AddToTreeHere)@

    According to your post, it looks like I was supposed to have created my own class of QTreeWidget with and include the signal code in its constructor, and create my tree by instantiating that class. Am I correct? I'm fairly new to OOP so it's not always my first instinct to do things this way.

    Thanks so much!



  • You should be able to everything in your mainwindow initialiser as shown below, I was just being a bit lazy in my example ;o)

    @
    from PyQt4.QtGui import *

    class Widget(QMainWindow):
    def init(self, parent=None):
    QMainWindow.init(self, parent)

        self.tree=QTreeWidget(self)
        self.tree.insertTopLevelItems(0, [QTreeWidgetItem(self.tree, ["Item %d" % i]) for i in range(3)])
        self.tree.itemDoubleClicked.connect(self.addToTreeHere)
    
        self.setCentralWidget(self.tree)
    
    def addToTreeHere(self):
        print "Item has been double clicked..."
    

    if name=="main":
    from sys import argv, exit
    a=QApplication(argv)
    w=Widget()
    w.show()
    w.raise_()
    exit(a.exec_())
    @



  • Your answer was very helpful but now I'm confused about a few of my next steps -- I'm sure my questions below have very simple answers. Please see below:

    @

    THIS OCCURS WITHIN THE CONSTRUCTOR FOR A TAB, WHICH HAS SEVERAL OTHER ITEMS IN IT:

    There are several other tabs which each have their own listbox and treeview

    Everything is generated dynamically from data in a parsed spreadsheet file so they don't have unique names

     self.listbox = QtGui.QListWidget()
    
     # then several lines adding items to the listbox, then: 
    
     self.tree = MyTreeWidget(self)   # where 'self' refers to the tab
    
      # then, several lines adding items to the tree
      # then, later:
    

    class MyTreeWidget(QTreeWidget):
    def init(self, tab):
    self.tab = tab
    QTreeWidget.init(self)
    print(tab)
    self.itemDoubleClicked.connect(self.addToTreeHere)

    def addToTreeHere(self):
        print("Item has been double clicked...")
        sender = self.sender()
    

    #####################################################
    print(sender) # QUESTION 1: refers to here
    #####################################################

    #############################################################
    items = self.tab.listbox.selectedItems() # QUESTION 2: SEE BELOW
    #############################################################
    for item in items:
    print(item.text())
    #[SENDERITEMCLICKED].addChildren(items)@

    QUESTION 1: How do I refer to the treeview ITEM that was clicked to call the function. self.sender() seems to refer to the entire treeview, not to the clicked item within the treeview...

    QUESTION 2: Is this the correct/pythonic way to refer to the listbox? This seems to work but I'm self-teaching, so I'm sure I come up with a lot of complicated techniques because I'm ignorant of a more elegant solution.

    QUESTION 3: I can't figure out how to change the background color for an individual tree item. I can change the foreground color with:

    @redbrush = QBrush()
    redbrush.setColor(QColor('red')
    item.setForeground(0,redbrush)@

    but the following doesn't work:

    @item.setBackground(0,redbrush)@



  • Okay, here goes:

    Question 1:
    If you look at the "docs":http://doc.qt.nokia.com/4.7-snapshot/qtreewidget.html#itemDoubleClicked for the itemDoubleClicked signal you'll see it passes the item and column that were triggered to any connected slot. Therefore, you don't need to use sender(), just respec your slot as follow:

    @
    @pyqtSlot(QTreeWidgetItem, int)
    def addToTreeHere(self, item, column):
    print "Item has been double clicked:", item.text(column)
    item.setBackground(column, QBrush(Qt.red))
    @

    The decorator isn't stricly necessary in this case, but it is good practice and very useful for signals with multiple signatures. See "here":http://www.riverbankcomputing.com/static/Docs/PyQt4/html/new_style_signals_slots.html for more details and examples

    Question 2:
    The short answer is: yes, that's fine and correct. However, unless you need the QTreeWidget to have a reference to the tab, just pass a reference to the QListWidget instead, i.e.:

    @
    self.tree = MyTreeWidget(self.listbox)
    @

    This will make for less typing ;o)

    Question 3:
    See code example for Question 1, line 4: this works fine for me, see how you get on. Bear in mind, if the focus is on this item, it will be the highlight color until the focus is moved (i.e., single click on another item).

    To conclude...
    Hope this helps. Also, if you're a PyQt newbie and want some pretty awesome tutorials, have a look "here":http://zetcode.com/tutorials/pyqt4/. Happy developing ;o)



  • jazzycamel -- thank you for all of you help. You have answered all of my questions with clarity and I appreciate it immensely.

    I have gone through the zetcode tutorials and find them very helpful (they're the only reason I've been able to get as far as I have), but whenever I've tried to do something a bit outside of the tutorial's scope, it's taken a lot of trial and error.

    At first I found the nokia documentation a bit overwhelming, but as I'm starting to develop an understanding of the syntax, the docs make more sense to me.

    Thanks again for all your help!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.