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

師從名劍山發表於2022-04-09

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

相關文章