Qt 重載QComboBox,實現右側刪除鍵

Qt 重載QComboBox,實現右側刪除鍵

前言

最近在做一個項目,這個項目用到一個QComboBox下拉框,做出來之後,功能都是能夠正常實現的。但是我想要實現之前看到的一個網頁的下拉框效果:
img

所以我就琢磨怎麼來實現這種效果。

方案

簡單來說,就是當QComboBox有選中內容時,滑鼠移動到右側下拉箭頭時,下拉箭頭變成一個叉號,點擊之後會將當前選中的內容刪除;

設置下拉箭頭圖標

首先,我想到了讓這個下拉箭頭變換圖標的方式,通過setProperty來設置動態屬性,並設置樣式,來設置不同圖標。具體方式請看我之前寫的這篇博文Qt通過setProperty來達到設置控制項的不同樣式表。然後將訊號currentIndexChanged和設置圖標的槽函數連接起來,程式碼如下:

// 連接訊號
connect(this, SIGNAL(currentIndexChanged(int)),
        this,SLOT(slot_setPopupType(int)));

void MyComboBox::slot_setPopupType(const int &index)
{
    QString type;
    // 根據當前下標來判斷是不是有內容
    type = (index == -1 ? "popup" : "close");
    // 設置屬性
    setProperty("Type", type);
    // 設置屬性後,必須重新刷新一下樣式
    style()->polish(this);
}

設置QComboBox內容為空

在實踐的過程中,我苦於清除按鍵的功能設計,怎樣才能讓QComboBox的內容為空呢?
然後我搜索後發現了這個
setCurrentIndex(-1);
當設置當前下標為-1時,就會將QComboBox的內容置空;

自定義showPopup函數

如果你需要對下拉的過程進行自定義,就需要重載函數showPopup。我這裡不需要進行自定義,所以我就沒有進行重載了;

定位滑鼠

但是,我們要怎麼確定滑鼠按下的位置是下拉框呢?
我最開始的方案是根據滑鼠點擊的位置來確定,但是根據你樣式表設置的不同,你的這個下拉箭頭的大小就會不同,我想盡了各種辦法,都沒有找到怎麼去獲取這個下拉箭頭的大小的方法,所以獲取的位置就可能會因為不同的樣式會有偏差。後面我想到自帶的QComboBox不是有對下拉框進行點擊事件嗎?或許能從源碼里找到答案。
img
這裡重要的點在
sc == QStyle::SC_ComboBoxArrow
看到這裡,我就知道要怎麼去判斷滑鼠點擊的位置是下拉框了;

if (property("Type") == "close") {
    // 當sc == SC_ComboBoxArrow代表,按下的位置為下拉箭頭的位置
    if (e->button() == Qt::LeftButton
            && sc == QStyle::SC_ComboBoxArrow) {
        setCurrentIndex(-1);
    } else {
        QComboBox::showPopup();
    }
    return;
}

屏蔽滑鼠右鍵

然後又出現了一個滑鼠右擊這個comboBox,也會將下拉框展開的問題,所以我們需要將滑鼠右鍵進行屏蔽;

if (e->button() == Qt::RightButton) {
    return;
}

最終控制下拉程式碼

void MyComboBox::mouseReleaseEvent(QMouseEvent *e)
{
    QStyleOptionComboBox opt;
    this->initStyleOption(&opt);
    // 此處是獲取滑鼠按下的坐標對應的子控制項
    QStyle::SubControl sc = this->style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, e->pos(), this);

    // 屏蔽右鍵
    if (e->button() == Qt::RightButton) {
        return;
    }

    if (property("Type") == "close") {
        // 當sc == SC_ComboBoxArrow代表,按下的位置為下拉箭頭的位置
        if (e->button() == Qt::LeftButton
                && sc == QStyle::SC_ComboBoxArrow) {
            setCurrentIndex(-1);
        } else {
            QComboBox::showPopup();
        }
        return;
    }

    return QComboBox::mousePressEvent(e);
}

void MyComboBox::mousePressEvent(QMouseEvent *e)
{
    // 此處為了禁止按住拖動時會展開下拉菜單
    Q_UNUSED(e);
    return;
}

效果圖

img

程式碼下載

程式碼下載請看gitee MyComboBox