PyQT:树视图列中的 QPushButton 委托 [英] PyQT: QPushButton delegate in column of a treeview

查看:59
本文介绍了PyQT:树视图列中的 QPushButton 委托的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道在

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

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

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

一些进一步的评论

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

另一个缺点是项目的文本可能会被按钮覆盖,对于某些样式,这可能会导致一些丑陋的外观.您可以决定使用 fontMetrics 的 elideText() 方法(通过减去按钮的宽度)来删除文本,或者如果项目文本的 fontMetrics 不允许,则简单地屏蔽"按钮的右侧完整显示.

但是要小心:如果您有多个列,则按钮的隐藏"右侧部分根本不会被隐藏,但它将成为下一列的一部分.

I know there has been a question with the same goal in C++, but I didn't succeed implementing a button delegate in a treeview. So I ask a new question here, even if I know there was a previous question with the same goal. I just ask for further explanation.

So since a few days, I manage to implement a multi-node tree model within a treeview thanks to this video tutorial with the code source here and here but now I would like to add a delegate pushbutton next to each child of the last level of the tree model. After consulting Qt documentation about model/view programming, searching around and reading chapter 14, 15 and 16 from the book of Mark Summerfield Rapid GUI Programming with Python and QT and searching how to add Qwidget delegate by using createEditor(), setEditordata() and setModelData() I still struggle to display "The" button…

So I started to create the button class delegate:

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

Here you see that I didn't implement setEditordata() and setModelData(), because I have connected the button to def handle_button(self) and I just want to print the name of the child for the moment (just to make it simple).

I use setItemDelegateForColumn(int, AbstractItemDelegate) for setting up the delegate I also know that for displaying the button you have to specify this method to the treeview QAbstractItemView.openPersistentEditor(QModelIndex). But I don't know what to put as argument...

Again I am sorry to "repost" a question but at the moment I am in a dead end...I don't know where to start.

I write my code in Python, but if you answer in C++ I will figure it out, don't worry.

Thanks again for the help.

解决方案

Using setIndexWidget might be a solution, but since you have to set it for every last child item, this might require too much coding and could be prone to bugs and headaches... I'd suggest to draw the button directly in the delegate using QStyle's methods.

This is a simple implementation:

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)

And here's how it could look like...

Obviously you have to implement your own signal, but, since editorEvent automatically handles mouse events, this would be a simple task of detecting if the event.pos() is within the "virtual" button QRect.

In the example above I added a simple hover detection, which sets the "mouse-over look" on the button whenever the mouse pointer is above the item, but you might prefer to use the hover style only when the pointer is actually on the button.

Since paint doesn't give you the possibility to detect the mouse position, there are two possible solutions. Either you use a delegate exclusively for the view and add the view's instance as a parameter when you init the delegate (then you can easily use mapFromGlobal with QtGui.QCursor.pos() and retrieve its position according to the option.rect - just remember that you have to map it to the viewport, not the view); or you create a specific UserRole in which you write the event.pos() to the item from the editorEvent method, then read it from the paint method. To achieve that, mouseTracking must be enabled on the view.

Some further comments

As you can imagine, the look of the item will have issues when the tree level is too deep and the view's width isn't wide enough to show the item itself. You could look into the option.rect's available size, if you don't want to hide the item or don't show the button if there's not enough space available.

Another drawback is that the item's text might be painted over by the button, with some styles this could result in some ugly appearance. You could decide to elide the text using fontMetrics' elideText() method (by subctracting the button's width) or simply "mask" the right side of the button if the fontMetrics of the item's text does not allow it to be completely shown.

Be careful with that, though: if you have more than one column, the "hidden" right part of the button won't be hidden at all, but it will be part of the next column.

这篇关于PyQT:树视图列中的 QPushButton 委托的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆