Goal
I want the user to be able to click on a QIcon to do something. That is, I want to connect a mouse click event, within a QIcon, to a slot.
What I have tried
In my example (below) I am using a tree view, and when the user clicks one of the icons, I want to add a child to that node.
I have tried doing this by reimplementing mousePressEvent
for the icon, but I'm not sure how to do so for icons (which by default serve a purely decorator role) within a treeviewmodel.
The code, in simplified form, is as below:
from PySide import QtGui, QtCore
import icons_rc
class Node(object):
def __init__(self, name, parentNode=None):
self.name = name
self.childNodes = []
self.parentNode = parentNode
if parentNode is not None: #if self has a parent, then add self node to parent in tree
parentNode.addChild(self)
def addChild(self, childNode):
self.childNodes.append(childNode) #
def setName(self, name):
self.name=name
def data(self):
return self.name
def child(self, row):
return self.childNodes[row]
def childCount(self):
return len(self.childNodes)
def parent(self):
return self.parentNode
def row(self):
if self.parentNode is not None: #if self has a parent, then return row of self
return self.parentNode.childNodes.index(self)
class TreeModel(QtCore.QAbstractItemModel):
#Inputs: node, Qobject
def __init__(self, root, parent=None):
QtCore.QAbstractItemModel.__init__(self, parent)
self.rootNode = root
def rowCount(self, parentIndex=QtCore.QModelIndex()):
if not parentIndex.isValid():
parentNode = self.rootNode
else:
parentNode = parentIndex.internalPointer() #picks out parent node of tree
return parentNode.childCount()
def columnCount(self, parentIndex=QtCore.QModelIndex()):
return 1
def flags(self,index):
return QtCore.Qt.ItemIsEnabled
def data(self, index, role):
if not index.isValid():
return None
node=index.internalPointer()
#role--editrole here so text doesn't disappear when you double click
if role == QtCore.Qt.DisplayRole:
if index.column() == 0:
return node.data() #node.data method defined above (string)
#icons are shown by using a decoration role
if role==QtCore.Qt.DecorationRole:
if index.column() == 0:
return QtGui.QIcon(QtGui.QPixmap(":/images/add.png"))
def setData(self, index, value, role=QtCore.Qt.EditRole):
if index.isValid():
return True
else:
return False
def getNode(self,index):
if index.isValid():
node=index.internalPointer()
if node:
return node
return self.rootNode
def parent(self, childIndex):
if not childIndex.isValid():
return QtCore.QModelIndex()
childNode = self.getNode(childIndex)
parentNode = childNode.parent()
if parentNode == self.rootNode:
return QtCore.QModelIndex()
return self.createIndex(parentNode.row(), 0, parentNode)
def index(self, row, column, parentIndex):
if not self.hasIndex(row, column, parentIndex):
return QtCore.QModelIndex()
parentNode=self.getNode(parentIndex)
childNode = parentNode.child(row) #implemented above
if childNode:
return self.createIndex(row, 0, childNode) #row/col/object yields index
else:
return QtCore.QModelIndex()
def main():
import sys
qtApp=QtGui.QApplication(sys.argv)
rootNode = Node("Hips") #for some reason, by design, this will not show
childNode0 = Node("LeftLeg", rootNode)
childNode1 = Node("RightLeg", rootNode)
childNode2 = Node("RightAnkle", childNode1)
childNode3 = Node("Middle toe", childNode2)
childNode4 = Node("Pirate flank toe", childNode2)
childNode5 = Node("Pinky toe", childNode2)
model=TreeModel(rootNode)
treeView = QtGui.QTreeView()
treeView.show() #opens empty window
treeView.setModel(model)
sys.exit(qtApp.exec_())
if __name__ == "__main__":
main()
Basically I want to build an event handler that adds a child when I click an icon, an icon which is given in add.png. Is there some sneaky route to reimplement mouseClickEvent
or other functions for icons? I have made zero headway on this problem with Google.
I tried subclassing QIcon, and reimplementing mousePressEvent. The goal is to use this revised icon class within TreeModel.data(). So far I have had no luck getting the class to work. Here's what I tried:
class ClickableQIcon(QtGui.QIcon):
def __init__(self, iconPixmap, parent):
QtGui.QIcon.__init__(self, iconPixmap, parent)
def mousePressEvent(self, event):
print "This time you pressed in an icon"
Where I would feed it something like iconPixmap=QtGui.QIcon(QtGui.QPixmap(":/images/add.png"))
as one of the inputs in the calling function. It doesn't work, I only include it to show the kind of solution I was hoping to find.
Potentially relevant posts: