PyQT:树视图列中的QPushButton委托

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PyQT:树视图列中的QPushButton委托相关的知识,希望对你有一定的参考价值。

我知道在C++中有一个同样目标的问题,但我没有成功在树视图中实现按钮委托。所以我在这里提出一个新问题,即使我知道之前有一个同样目标的问题。我只想要进一步解释。

因此,几天后,我设法在树视图中实现一个多节点树模型,这要归功于video tutorial和代码源herehere但现在我想在最后一级的每个子节点旁边添加一个委托按钮。树模型。在查阅关于模型/视图编程的Qt文档后,搜索around并阅读Mark Summerfield Rapid GUI Programming with Python and QT一书中的第14,15和16章,并使用createEditor()setEditordata()setModelData()搜索如何添加Qwidget委托我仍然很难显示“The”按钮...

所以我开始创建按钮类委托:

class ButtonDelegate(QtGui.QItemDelegate):
    """
    A delegate that places a fully functioning Button in every
    cell of the column to which it's applied
    """

    def __init__(self, parent):
        QtGui.QItemDelegate.__init__(self, parent)

    def createEditor(self, parent, option, index):
        button = QtGui.QPushButton("Simple button", parent)
        self.connect(button, QtCore.SIGNAL("clicked()"), self, QtCore.SLOT("handle_button()"))
        return button

    @QtCore.pyqtSlot()
    def handle_button(self):
        sender = self.sender()
        print("Button pushed: {}".format(self.sender()))

在这里你看到我没有实现setEditordata()setModelData(),因为我已经将按钮连接到def handle_button(self)并且我只是想打印孩子的名字暂时(只是为了简化)。

我使用setItemDelegateForColumn(int, AbstractItemDelegate)来设置委托我也知道,为了显示按钮,你必须将这个方法指定给treeview QAbstractItemView.openPersistentEditor(QModelIndex)。但我不知道该把什么作为论点......

我很抱歉“重新发布”一个问题,但此刻我已经走到了尽头...我不知道从哪里开始。

我用Python编写代码,但如果你用C ++回答我会弄清楚,不要担心。

再次感谢您的帮助。

答案

使用setIndexWidget可能是一个解决方案,但由于你必须为每个最后一个子项设置它,这可能需要太多的编码,并且可能容易出现错误和头痛...我建议直接在委托中使用按钮QStyle的方法。

这是一个简单的实现:

class ButtonDelegate(QtGui.QStyledItemDelegate):
    def paint(self, painter, option, index):
        QtGui.QStyledItemDelegate.paint(self, painter, option, index)
        if index.model().hasChildren(index):
            return
        rect = option.rect
        btn = QtGui.QStyleOptionButton()
        btn.rect = QtCore.QRect(rect.left() + rect.width() - 30, rect.top(), 30, rect.height())
        btn.text = '...'
        btn.state = QtGui.QStyle.State_Enabled|(QtGui.QStyle.State_MouseOver if option.state & QtGui.QStyle.State_MouseOver else QtGui.QStyle.State_None)
        QtGui.QApplication.style().drawControl(QtGui.QStyle.CE_PushButton, btn, painter)

这是它的样子......

Example of implementation

显然你必须实现自己的信号,但是,由于editorEvent自动处理鼠标事件,这将是一个简单的任务,检测event.pos()是否在“虚拟”按钮QRect

在上面的示例中,我添加了一个简单的悬停检测,只要鼠标指针位于项目上方,就会在按钮上设置“鼠标悬停外观”,但是只有当指针实际位于按钮上时,您可能更喜欢使用悬停样式。

由于paint无法检测到鼠标位置,因此有两种可能的解决方案。您可以使用专门用于视图的委托,并在初始化委托时将视图的实例添加为参数(然后您可以轻松地将mapFromGlobalQtGui.QCursor.pos()一起使用并根据option.rect检索其位置 - 只需记住您必须将其映射到viewport,不是观点);或者你创建一个特定的UserRole,你在其中用event.pos()方法将editorEvent写入项目,然后从paint方法中读取它。要实现这一点,必须在视图上启用mouseTracking

进一步评论

可以想象,当树级太深而视图的宽度不足以显示项目本身时,项目的外观会出现问题。您可以查看option.rect的可用尺寸,如果您不想隐藏该项目,或者如果没有足够的可用空间则不显示该按钮。

另一个缺点是该项目的文字可能被按钮涂抹,有些样式可能会导致一些丑陋的外观。如果项目文本的fontMetrics不允许完全显示,您可以决定使用fontMetrics的elideText()方法(通过减去按钮的宽度)来消除文本,或者简单地“屏蔽”按钮的右侧。

但请注意:如果您有多个列,则按钮的“隐藏”右侧部分将不会被隐藏,但它将成为下一列的一部分。

以上是关于PyQT:树视图列中的QPushButton委托的主要内容,如果未能解决你的问题,请参考以下文章

从 PyQt 中的 QPushButton 获取文本

突出显示qpushbutton pyqt中的单个字符[重复]

PyQt4:使用 QPushButton 小部件从 QList 小部件中删除项目

PyQt / Qt,带有自定义委托的表格视图以使用省略号来处理文本溢出单元格

PyQt5 QPushButton setSyleSheet 按下时不改变按钮颜色

PyQt4 QPushButton 文本和图标对齐