【问题标题】:How to make a QIcon clickable?如何使 QIcon 可点击?
【发布时间】:2014-09-12 13:05:42
【问题描述】:

目标

我希望用户能够单击 QIcon 来执行某些操作。也就是说,我想将 QIcon 内的鼠标单击事件连接到插槽。

我的尝试

在我的示例(如下)中,我使用树视图,当用户单击其中一个图标时,我想向该节点添加一个子节点。

我已经尝试通过为图标重新实现 mousePressEvent 来做到这一点,但我不确定如何为树视图模型中的图标(默认情况下充当纯粹的装饰角色)这样做。

代码简化如下:

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()

基本上,我想构建一个事件处理程序,当我单击一个图标时添加一个子项,该图标在 add.png 中给出。是否有一些偷偷摸摸的途径来重新实现mouseClickEvent 或其他图标功能?我在 Google 的这个问题上取得了零进展。

我尝试继承 QIcon,并重新实现 mousePressEvent。目标是在 TreeModel.data() 中使用这个修改后的图标类。到目前为止,我还没有让班级开始工作。这是我尝试过的:

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"   

我会将iconPixmap=QtGui.QIcon(QtGui.QPixmap(":/images/add.png")) 之类的东西作为调用函数中的输入之一提供给它。它不起作用,我只包含它以显示我希望找到的那种解决方案。

可能相关的帖子:

Button Icon Change on Click

QIcon inside combobox

【问题讨论】:

    标签: python qt pyqt pyside


    【解决方案1】:

    您不能为QIcon 重新实现事件处理程序,因为它是一个简单的图像容器,与事件处理无关。这就是为什么你的扩展 QIcon 类没有做任何事情的原因。

    另外QTreeView 默认只绘制装饰图标。

    您可以在树视图中使用自定义项目委托。 QTreeView 继承自 QAbstractItemView,它有几个 setItemDelegate 方法 (documentation)。然后要么扩展QItemDelegate,要么实现QAbstractItemDelegate

    使用setIndexWidget() 设置自定义小部件可能更快一点。

    如果图标始终相同,您甚至可以在QTreeView 上使用样式表。 (documentation)

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-07
    • 2019-08-05
    • 2016-02-13
    • 2015-02-07
    • 2014-11-16
    • 2013-09-20
    • 1970-01-01
    相关资源
    最近更新 更多