天天看點

Qt 之模型/視圖(自定義按鈕)簡述效果QStyledItemDelegate衍伸

簡述

衍伸前面的章節,我們對QTableView實作了資料顯示、自定義排序、顯示複選框、進度條等功能的實作,本節主要針對自定義按鈕進行講解,這節過後,也希望大家對自定義有更深入的了解,在以後的功能開發過程中,相信無論遇到什麼樣式形式,我們都可以很好地實作。

|

版權聲明:一去、二三裡,未經部落客允許不得轉載。

效果

Qt 之模型/視圖(自定義按鈕)簡述效果QStyledItemDelegate衍伸

QStyledItemDelegate

源碼

.h

包含顯示按鈕需要用到的智能指針,按鈕的寬度、高度、按鈕之間的間距、滑鼠的坐标等。

class TableViewDelegate: public QStyledItemDelegate
{
    Q_OBJECT

public:
    explicit TableViewDelegate(QWidget *parent = );
    ~TableViewDelegate();
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index);

signals:
    void open(const QModelIndex &index);
    void deleteData(const QModelIndex &index);

private:
    QPoint m_mousePoint;  // 滑鼠位置
    QScopedPointer<QPushButton> m_pOpenButton;
    QScopedPointer<QPushButton> m_pDeleteButton;
    QStringList m_list;
    int m_nSpacing;  // 按鈕之間的間距
    int m_nWidth;  // 按鈕寬度
    int m_nHeight;  // 按鈕高度
    int m_nType;  // 按鈕狀态-1:劃過 2:按下
};
           

.cpp

主要設定按鈕樣式,實作滑鼠劃過、按下,響應滑鼠事件等操作。

TableViewDelegate::TableViewDelegate(QWidget *parent)
    : QStyledItemDelegate(parent),
      m_pOpenButton(new QPushButton()),
      m_pDeleteButton(new QPushButton()),
      m_nSpacing(),
      m_nWidth(),
      m_nHeight()
{
    // 設定按鈕正常、劃過、按下樣式
    m_pOpenButton->setStyleSheet("QPushButton {border: none; background-color: transparent; image:url(:/Images/open);} \
                                 QPushButton:hover {image:url(:/Images/openHover);} \
                                 QPushButton:pressed {image:url(:/Images/openPressed);}");

    m_pDeleteButton->setStyleSheet("QPushButton {border: none; background-color: transparent; image:url(:/Images/delete);} \
                                 QPushButton:hover {image:url(:/Images/deleteHover);} \
                                 QPushButton:pressed {image:url(:/Images/deletePressed);}");
    m_list << QStringLiteral("打開") << QStringLiteral("删除");
}

TableViewDelegate::~TableViewDelegate()
{

}

// 繪制按鈕
void TableViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItem viewOption(option);
    initStyleOption(&viewOption, index);
    if (option.state.testFlag(QStyle::State_HasFocus))
        viewOption.state = viewOption.state ^ QStyle::State_HasFocus;

    QStyledItemDelegate::paint(painter, viewOption, index);

    if (index.column() == FILE_OPERATE_COLUMN)
    {
        // 計算按鈕顯示區域
        int nCount = m_list.count();
        int nHalf = (option.rect.width() - m_nWidth * nCount - m_nSpacing * (nCount - )) / ;
        int nTop = (option.rect.height() - m_nHeight) / ;

        for (int i = ; i < nCount; ++i)
        {
            // 繪制按鈕
            QStyleOptionButton button;
            button.rect = QRect(option.rect.left() + nHalf + m_nWidth * i + m_nSpacing * i,
                                option.rect.top() + nTop,  m_nWidth, m_nHeight);
            button.state |= QStyle::State_Enabled;
            //button.iconSize = QSize(16, 16);
            //button.icon = QIcon(QString(":/Images/%1").arg(m_list.at(i)));

            if (button.rect.contains(m_mousePoint))
            {
                if (m_nType == )
                {
                    button.state |= QStyle::State_MouseOver;
                    //button.icon = QIcon(QString(":/Images/%1Hover").arg(m_list.at(i)));
                }
                else if (m_nType == )
                {
                    button.state |= QStyle::State_Sunken;
                    //button.icon = QIcon(QString(":/Images/%1Pressed").arg(m_list.at(i)));
                }
            }

            QWidget *pWidget = (i == ) ? m_pOpenButton.data() : m_pDeleteButton.data();
            QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter, pWidget);
        }
    }
}

// 響應按鈕事件 - 劃過、按下
bool TableViewDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
{
    if (index.column() != FILE_OPERATE_COLUMN)
        return false;

    m_nType = -;
    bool bRepaint = false;
    QMouseEvent *pEvent = static_cast<QMouseEvent *> (event);
    m_mousePoint = pEvent->pos();

    int nCount = m_list.count();
    int nHalf = (option.rect.width() - m_nWidth * nCount - m_nSpacing * (nCount - )) / ;
    int nTop = (option.rect.height() - m_nHeight) / ;

    // 還原滑鼠樣式
    QApplication::restoreOverrideCursor();

    for (int i = ; i < nCount; ++i)
    {
        QStyleOptionButton button;
        button.rect = QRect(option.rect.left() + nHalf + m_nWidth * i + m_nSpacing * i,
                            option.rect.top() + nTop,  m_nWidth, m_nHeight);

        // 滑鼠位于按鈕之上
        if (!button.rect.contains(m_mousePoint))
            continue;

        bRepaint = true;
        switch (event->type())
        {
        // 滑鼠滑過
        case QEvent::MouseMove:
        {
            // 設定滑鼠樣式為手型
            QApplication::setOverrideCursor(Qt::PointingHandCursor);

            m_nType = ;
            QToolTip::showText(pEvent->globalPos(), m_list.at(i));
            break;
        }
        // 滑鼠按下
        case QEvent::MouseButtonPress:
        {
            m_nType = ;
            break;
        }
        // 滑鼠釋放
        case QEvent::MouseButtonRelease:
        {
            if (i == )
            {
                emit open(index);
            }
            else
            {
                emit deleteData(index);
            }
            break;
        }
        default:
            break;
        }
    }

    return bRepaint;
}
           

衍伸

通過上面的實作,我們可以自定義按鈕的樣式、文本、顯示區域、等,我們也可以通過QStyleOptionButton的icon和iconSize來設定按鈕的圖示與圖示大小,通過響應按鈕來實作我們自己的事件。

繼續閱讀