【问题标题】:button delegate issue按钮委托问题
【发布时间】:2014-05-27 19:22:18
【问题描述】:

我希望有人可以帮助我解决这个困扰了我一段时间的烦人问题。我已经使用附加的代码在委托列的表格视图中插入按钮进行了管理。

问题是要按下按钮,我需要通过双击“激活”包含单元格。一旦单元格处于活动状态,我就可以按下按钮,所以我总共需要 3 次点击才能按下它。这可能会让您的普通用户感到困惑。

我把这个问题发到了pyqt邮件列表,得到的答案是:

"发生的情况是,当 TableWidget 收到点击时,它 创建了一个编辑器,但该编辑器还没有收到 点击。在大多数情况下这是完美的,但如果你画 它不是一个按钮。”

有人来过这里吗?

提前致谢, 危机

class AnimLinkButtons(QtGui.QStyledItemDelegate):
    mouse_isPressed = False

    def __init__(self, parent = None):
        QtGui.QStyledItemDelegate.__init__(self, parent)

    def createEditor(self, parent, option, index):
        column = index.column()
        button = QtGui.QPushButton(parent)
        button.setText(self.text(index))
        ButtonLoc = self.ButtonLocation(option)
        button.setGeometry(ButtonLoc)
        Cellvalue = index.model().data(index, QtCore.Qt.EditRole)
        row = index.row()
        AssetId = index.model().data(index.model().index(row, 0)).toString()

        AnimTurntablePath = shotsGetData.getAssetTurntablePath(AssetId)
        browsePath = shotsGetData.getAssetPath(AssetId)
        #toAvidComp = shotsGetData.gettoAvidComp(ShotId)

        # Connect to button
        button.clicked.connect(lambda: self.mousePressEvent(index, browsePath, AssetTurntablePath))
        return button

    def setEditorData(self, editor, index):
        button = editor
        if not button:
            return

    def setModelData(self, editor, model, index):
        button = editor
        if not button:
            return

    def updateEditorGeometry(self, editor, option, index):
        ButtonLoc = self.ButtonLocation(option)
        editor.setGeometry(ButtonLoc)

    def paint(self, painter, option, index):
        opt = QtGui.QStyleOptionButton()
        #opt.icon = self.icon()
        opt.text = self.text(index)
        opt.rect = option.rect
        opt.palette = option.palette
        opt.rect = self.ButtonLocation(opt)
        QtGui.QApplication.style().drawControl(QtGui.QStyle.CE_PushButton, opt, painter)

    def ButtonLocation(self,  option):
        r = option.rect
        x = r.left() + 10
        y = r.top() + 10
        w = 30;
        h = 30
        return QRect(x,y,w,h);

    def text(self,  index):
        #print self.column
        column = index.column()
        if column == 7:
            return QtCore.QString("Mov")


    def mousePressEvent(self, index, browsePath , AssetTurntablePath):
        column = index.column()
        print "PRESSSED"

        if column == 7:
            subprocess.Popen(AnimTurntablePath, shell=True)

【问题讨论】:

    标签: python pyqt qitemdelegate


    【解决方案1】:

    我最近做了类似的东西。如果您在createEditor 中创建了按钮,您将在编辑模式下激活它。当您双击单元格时会发生这种情况。所以邮件列表中的评论是正确的。

    在不编辑的情况下做到这一点很棘手。您在paint 方法中绘制的按钮只是一幅画,而不是实际的按钮。您应该监视editorEvent 的鼠标事件。为此,它会捕获 mouseButtonPressmouseButtonRelease 事件。

    此外,如果您想要单击按钮的“视觉”效果,事情就会变得复杂。无论如何,下面是一个基本的实现。它使用rowcolumn 发出buttonClicked 信号。

    注意:重绘依赖于委托也将接收来自其他列的事件这一事实。如果您将它与setItemDelegateForColumn 一起使用,这很可能不会正常工作,因为在这种情况下,委托将仅接收来自该列的事件。所以,我建议你将它用于整个表格并根据列进行绘制。

    class ButtonDelegate(QtGui.QStyledItemDelegate):
        buttonClicked = QtCore.pyqtSignal(int, int)
    
        def __init__(self, parent = None):
            super(ButtonDelegate, self).__init__(parent)
            self._pressed = None
    
        def paint(self, painter, option, index):
            painter.save()
            opt = QtGui.QStyleOptionButton()
            opt.text = index.data().toString()
            opt.rect = option.rect
            opt.palette = option.palette
            if self._pressed and self._pressed == (index.row(), index.column()):
                opt.state = QtGui.QStyle.State_Enabled | QtGui.QStyle.State_Sunken
            else:
                opt.state = QtGui.QStyle.State_Enabled | QtGui.QStyle.State_Raised
            QtGui.QApplication.style().drawControl(QtGui.QStyle.CE_PushButton, opt, painter)
            painter.restore()
    
        def editorEvent(self, event, model, option, index):
            if event.type() == QtCore.QEvent.MouseButtonPress:
                # store the position that is clicked
                self._pressed = (index.row(), index.column())
                return True
            elif event.type() == QtCore.QEvent.MouseButtonRelease:
                if self._pressed == (index.row(), index.column()):
                    # we are at the same place, so emit
                    self.buttonClicked.emit(*self._pressed)
                elif self._pressed:
                    # different place.
                    # force a repaint on the pressed cell by emitting a dataChanged
                    # Note: This is probably not the best idea
                    # but I've yet to find a better solution.
                    oldIndex = index.model().index(*self._pressed)
                    self._pressed = None
                    index.model().dataChanged.emit(oldIndex, oldIndex)
                self._pressed = None
                return True
            else:
                # for all other cases, default action will be fine
                return super(ButtonDelegate, self).editorEvent(event, model, option, index)
    

    【讨论】:

    • 感谢 Avaris 在此问题上提供的帮助。您说不要使用 setItemDelegateForColumn,我应该使用什么来代替?我在邮件列表中也收到了回复,如果对您有帮助,请查看此示例:gulon.co.uk/2013/01/30/button-delegate-for-qtableviews 再次感谢!克里斯
    • @user1028826:我的意思是,使用setItemDelegate 为整个视图设置委托。这仅适用于视觉效果。如果您不想要它们,您可以使用任何方式放置此委托。至于例子,就是err,不是很好。它滥用代表做一些超出其目的的事情。最后你会创建很多QPushButtons。对于大型表,可能存在资源问题。
    【解决方案2】:

    问题是很久以前写的,所以我没有花很多时间来回答...但是前几天也遇到了同样的问题。在stackoverflow上找到了解决方案,但找不到帖子了,忘记了书签和upvote...但仍然有github上解决方案文件的链接!

    See her for example

    重要的是在 QTableView 上使用openPersistentEditor(index)。在初始化视图时调用它,您的委托小部件将立即被绘制。

    如果您使用代理模型,请注意在调用 openPersistentEditor(index) 时使用代理模型的 QModelInstances。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-23
      相关资源
      最近更新 更多