3

我正在尝试使 QStyledItemDelegate 的行为类似于我编写的自定义 QWidget,因此我可以将代码切换为模型/视图方法。

自定义 QWidget 是一个复杂的按钮,它在鼠标悬停时在其角落显示四个“子按钮”(因此总共有五个信号)。它也可以通过自定义拖动像素图进行拖放。为此,我使用了 mousePressEvent、mouseReleaseEvent、mouseMoveEvent、enterEvent 和 leaveEvent。这是有和没有鼠标悬停时显示的“子按钮”的样子: 在此处输入图像描述

此后,我将主要代码切换为使用模型/视图方法,并尝试将此小部件用作自定义 ListView 的 QStyledItemDelegate。我尝试将自定义小部件分配为这样的编辑器:

class ToolButtonDelegate( QStyledItemDelegate ):

    def __init__( self, parent=None ):
        super( ToolButtonDelegate, self).__init__( parent )
        self.parent = parent

    def createEditor( self, parent, option, index ):
        if not index.isValid():
            return False
        btn = FancyButton( index.data( Qt.UserRole ), parent=parent )
        return btn

这似乎很有希望,因为它为我单击的项目绘制了“FancyButton”类。但是,我需要这是一个鼠标悬停事件。经过更多研究后,我尝试将 QAbstractItemView.entered 插槽连接到 QAbstractItemView.edit 信号:

self.entered.connect( self.edit )

这仅适用于我将鼠标指针移到上方的第一项,然后出现以下错误:

edit: editing failed

所以现在我又遇到了这些问题:

  • 如何正确关闭编辑器(没有“QAbstractItemView.leave”事件或类似事件)。
  • 如何确保鼠标点击实际触发 FanyButton 类中的按钮,而不仅仅是与 QAbstractIremView 交互

我有一种感觉,我正朝着错误的方向前进。

4

2 回答 2

3

I'd urge you to go back to delegates instead of widgets, purely for performance reasons =)

You can work with delegates mouse over events in paint method using states, particularly QStyle::State_MouseOver. As for clicks on buttons you can override editorEvent which receives all mouse events and then work with regions of where mouse clicks occurred. For example:

void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if (option.state & QStyle::State_MouseOver)
    {
        // draw stuff which appears on mouse over
    } else {
        // draw stuff that appears when mouse is not over control
    }
 }

bool editorEvent(QEvent *event, QAbstractItemModel*, const QStyleOptionViewItem &option, const QModelIndex &index)
{
        // Emit a signal when the icon is clicked
        if(event->type() == QEvent::MouseButtonRelease)
        {
            QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
            QRect editButtonRect = editIcon.rect().translated(editIconPos(option));
            QRect deleteButtonRect = deleteIcon.rect().translated(deleteIconPos(option));

            if(editButtonRect.contains(mouseEvent->pos()))
            {
                emit editIndexClicked(index);
            } else if (deleteButtonRect.contains(mouseEvent->pos())) {
                emit deleteIndexClicked(index);
            }
        }
        return false;
    }

Also you can check out this topic HowTo create delegate for QTreeWidget?, this is for QTreeWidget, but I think same methods would apply to your case too.

于 2012-07-11T09:43:16.483 回答
0

AFAIK,您不能使用自定义小部件来查看列表/表格/树视图代表中的项目。您可以使用它们进行编辑,但如果视图模式需要重绘以外的任何内容,那么您将很难过。

我们通过拥有自己的容器小部件来解决这个问题,这些小部件监听模型事件并动态添加/删除项目小部件。真的很遗憾,因为它感觉很基本。

原因可能是视图应该很快并且能够显示很多项目,并且拥有很多小部件并不快,所以他们选择只允许自定义重绘功能(这允许他们使用justone 容器小部件,在不同区域具有自定义绘画。)

也许有办法解决它,如果是这样,我很高兴听到它。

更新

如果您需要捕获事件,也许您可​​以在容器视图中安装一个事件过滤器,然后使用QListView::indexAt找到正确的项目/小部件/委托将事件发送到?

然后,您可以在 mouseenter/leave 上使用openPersistentEditor和 closePersistentEditor 来启用编辑,即在项目上显示/关闭您的自定义小部件。

于 2012-07-02T07:47:54.177 回答