How to create delegate for QTreeWidget?

后端 未结 3 788
耶瑟儿~
耶瑟儿~ 2020-12-14 02:50

Here is what I\'m trying to do (all parents and children must have a close button on the right, in the future, only the hovered item will be able to show th

相关标签:
3条回答
  • 2020-12-14 03:11

    You can use a QItemDelegate with a QTreeWidget this way (example in PyQt, sorry):

    myTreeWidget = QtGui.QTreeWidget()
    myTreeWidget.setItemDelegate(myDelegate())
    
    class myDelegate(QtGui.QItemDelegate):
        def paint(self, painter, option, index):
    
            #Custom Draw Column 1
            if index.column() == 1:
                icon = QtGui.QIcon(index.data(QtCore.Qt.DecorationRole))
                if icon:
                    icon.paint(painter, option.rect)
                    #You'll probably want to pass a different QRect
    
            #Use the standard routine for other columns
            else:
                super(myDelegate, self).paint(painter, option, index)
    
    0 讨论(0)
  • 2020-12-14 03:19

    First, I should ask if you are really using a QTreeWidget, or rather a QTreeView? You cannot use custom delegates with a QTreeWidget according to the documentation for QTreeView, and will have to use a QTree*View* and some form of QAbstractItemModel for you to be able to use a custom delegate.

    Ah, scratch that. I see that you're calling setItemDelegateForColumn, which is a QTreeView function, but you should be aware of the difference, so I'm keeping the above paragraph. :)

    I would check that your model's flags() function is returning Qt::ItemIsEditable as part of its item flags. The createEditor() method is called whenever an edit event is reported by the view. (The view events that will trigger an edit depend on the model's EditTriggers) Usually a double-click on the delegate will trigger an edit by default, among other things.

    I doubt that you want the close button to appear only on double-click, though. To get the button to appear all the time, you'll have to reimplement the delegate's paint() function to draw a button, Among other things. I found Qt's StarDelegate example to be quite helpful in this regard, and I suspect you'll find it useful too.

    0 讨论(0)
  • 2020-12-14 03:32

    You can use the QStyledDelegate::paint function to draw the close icon, without using any widget, and the editorEvent to receive mouse events for the item, even if you don't use the editor or make the item editable.

    class CloseButton : public QStyledItemDelegate {
        Q_OBJECT
    public:
    
        explicit CloseButton(QObject *parent = 0, 
                             const QPixmap &closeIcon = QPixmap())
            : QStyledItemDelegate(parent)
            , m_closeIcon(closeIcon)
        {
            if(m_closeIcon.isNull())
            {
                m_closeIcon = qApp->style()
                    ->standardPixmap(QStyle::SP_DialogCloseButton);
            }
        }
    
        QPoint closeIconPos(const QStyleOptionViewItem &option) const {
            return QPoint(option.rect.right() - m_closeIcon.width() - margin,
                          option.rect.center().y() - m_closeIcon.height()/2);
        }
    
        void paint(QPainter *painter, const QStyleOptionViewItem &option,
                   const QModelIndex &index) const {
            QStyledItemDelegate::paint(painter, option, index);
            // Only display the close icon for top level items...
            if(!index.parent().isValid()
                    // ...and when the mouse is hovering the item
                    // (mouseTracking must be enabled on the view)
                    && (option.state & QStyle::State_MouseOver))
            {
                painter->drawPixmap(closeIconPos(option), m_closeIcon);
            }
        }
    
        QSize sizeHint(const QStyleOptionViewItem &option,
                       const QModelIndex &index) const
        {
            QSize size = QStyledItemDelegate::sizeHint(option, index);
    
            // Make some room for the close icon
            if(!index.parent().isValid()) {
                size.rwidth() += m_closeIcon.width() + margin * 2;
                size.setHeight(qMax(size.height(),
                                    m_closeIcon.height() + margin * 2));
            }
            return size;
        }
    
        bool editorEvent(QEvent *event, QAbstractItemModel *model,
                         const QStyleOptionViewItem &option,
                         const QModelIndex &index)
        {
            // Emit a signal when the icon is clicked
            if(!index.parent().isValid() &&
                    event->type() == QEvent::MouseButtonRelease) {
                QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
    
                QRect closeButtonRect = m_closeIcon.rect()
                        .translated(closeIconPos(option));
    
                if(closeButtonRect.contains(mouseEvent->pos()))
                {
                    emit closeIndexClicked(index);
                }
            }
            return false;
        }
    
    signals:
        void closeIndexClicked(const QModelIndex &);
    private:
        QPixmap m_closeIcon;
        static const int margin = 2; // pixels to keep arount the icon
    
        Q_DISABLE_COPY(CloseButton)
    };
    
    0 讨论(0)
提交回复
热议问题