Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
348 views
in Technique[技术] by (71.8m points)

c++ - How to create delegate for QTreeWidget?

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 the **close ** button):

enter image description here

My delegate code:

class CloseButton : public QItemDelegate
{
     Q_OBJECT

public:
     CloseButton( QObject* parent = 0 )
          : QItemDelegate( parent )
     {};

     QWidget* createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
     {
          if ( index.column() == 1 )
          {
               QToolButton* button = new QToolButton( parent );
               button->setIcon( QIcon( CLOSE_ICON ) );
               //button->setFixedSize( 16, 16 );
               //button->setAutoRaise( true );
               //button->setVisible( true );

               CONNECT( button, SIGNAL( clicked() ), this, SLOT( emitCommitData() ) );

               return button;
          }
          return ( new QWidget );
     }

private slots:
     void emitCommitData()
     {
          emit commitData( qobject_cast< QWidget* >( sender() ) );
     }

private:
     //Q_DISABLE_COPY( CloseButton );
};

With QTreeWidget connection code:

recipientsView()->setItemDelegateForColumn( 1, new CloseButton( this ) );

where recipientsView() is a simple QTreeWidget.

Problem is that QToolButtons are not shown at all (it must be in the second column, i.e. column index in the tree is 1). What I'm doing wrong?

I have checked already all Qt demo examples about delegates and the first Google result about QItemDelegate's and similar stuff.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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)
};

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...