QT之控件批量處理

當我們想要對大量的同類控件進行初始化或者使用時,有沒有一次性全部解決的方法呢,我們自然想到勇敢一個for語句去遍歷所有的控件,但是使用for的前提是要有一個“id”,這樣我們才能挨個遍歷, 即通過id去查找對應的控件,這點和字典很像,而Python提供的就有這樣的字典屬性,例如:

        '''
        Create a dictionary, we can find the corresponding label by key.
        '''
        self.label = {
            1: self.label_11, 21:self.label_11,
            2: self.label_12, 22: self.label_12,
            3: self.label_13, 23: self.label_13,
            4: self.label_14, 24: self.label_14,
            5: self.label_15, 25: self.label_15,
            6: self.label_21, 26: self.label_21,
            7: self.label_22, 27: self.label_22,
            8: self.label_23, 28: self.label_23,
            9: self.label_24, 29: self.label_24,
            10:self.label_25, 30:self.label_25,
            11:self.label_31, 31:self.label_31,
            12:self.label_32, 32:self.label_32,
            13:self.label_33, 33:self.label_33,
            14:self.label_34, 34:self.label_34,
            15:self.label_35, 35:self.label_35,
            16:self.label_41, 36:self.label_41,
            17:self.label_42, 37:self.label_42,
            18:self.label_43, 38:self.label_43,
            19:self.label_44, 39:self.label_44,
            20:self.label_45, 40:self.label_45
        }

但是QT中似弗並沒有這樣的字典類,不過QT提供了一種列表類QList

看一下QT官方幫助文檔

Detailed Description
QList<T> is one of Qt's generic container classes. It stores items in a list that provides fast index-based access and index-based insertions and removals.
QList<T>, QLinkedList<T>, and QVector<T> provide similar APIs and functionality. They are often interchangeable, but there are performance consequences. Here is an overview of use cases:
QVector should be your default first choice. QVector<T> will usually give better performance than QList<T>, because QVector<T> always stores its items sequentially in memory, where QList<T> will allocate its items on the heap unless sizeof(T) <= sizeof(void*) and T has been declared to be either a Q_MOVABLE_TYPE or a Q_PRIMITIVE_TYPE using Q_DECLARE_TYPEINFO. See the Pros and Cons of Using QList for an explanation.
However, QList is used throughout the Qt APIs for passing parameters and for returning values. Use QList to interface with those APIs.
If you need a real linked list, which guarantees constant time insertions mid-list and uses iterators to items rather than indexes, use QLinkedList.
Note: QVector and QVarLengthArray both guarantee C-compatible array layout. QList does not. This might be important if your application must interface with a C API.
Note: Iterators into a QLinkedList and references into heap-allocating QLists remain valid as long as the referenced items remain in the container. This is not true for iterators and references into a QVector and non-heap-allocating QLists.
Internally, QList<T> is represented as an array of T if sizeof(T) <= sizeof(void*) and T has been declared to be either a Q_MOVABLE_TYPE or a Q_PRIMITIVE_TYPE using Q_DECLARE_TYPEINFO. Otherwise, QList<T> is represented as an array of T* and the items are allocated on the heap.
The array representation allows very fast insertions and index-based access. The prepend() and append() operations are also very fast because QList preallocates memory at both ends of its internal array. (See Algorithmic Complexity for details.
Note, however, that when the conditions specified above are not met, each append or insert of a new item requires allocating the new item on the heap, and this per item allocation will make QVector a better choice for use cases that do a lot of appending or inserting, because QVector can allocate memory for many items in a single heap allocation.
Note that the internal array only ever gets bigger over the life of the list. It never shrinks. The internal array is deallocated by the destructor and by the assignment operator, when one list is assigned to another.

QList是Qt的一個通用容器類。它將項目存儲在一個列表中,該列表提供快速的基於索引的訪問和基於索引的插入和刪除。

再看一下官方示例

Here's an example of a QList that stores integers and a QList that stores QDate values:

  QList<int> integerList;
  QList<QDate> dateList;

這裏定義了一個整型列表和一個日期類的列表

而我們也同樣要定義一個這樣得到列表來保存所有的label控件

與官方示例不同的是,列表中的label都是指針類型,且指向QLabel

    QList<QPushButton *> Botton_list; /* 定義一個列表存放ui上的按鈕 */
    QList<QLabel *> frame_list; /* 定義一個列表存放底層Label */
    QList<QLabel *> label_list; /* 定義一個列表存放頂層Label */

使用方法如下

    QString button_style = "QPushButton{background-color:rgb(240,240,240);\
                            color:black;\
                            padding:4px;\
                            border-radius:4px;\
                            border:2px groove gray;\
                            border-style:outset;\
                            font:bold 14px;\
                            min-height:30;}" \
                            "QPushButton:pressed{backgroung-color:rgb(255,255,0);\
                                        border-style:inset;\
                                        padding-left:6px;\
                                        padding-top:6px;}"\
                            "QPushButton:hover{background-color:rgb(255,255,255)}"\
                            "QPushButton:!enabled{border:2px solid rgb(130,130,130);color:rgb(130,130,130);}";

    Botton_list = this->findChildren<QPushButton *>();
    foreach (QPushButton * btn, Botton_list) {
            btn->setStyleSheet(button_style);
    }

    /* 初始化列表 */
    frame_list << ui->frame_1 << ui->frame_2 << ui->frame_3 << ui->frame_4 << ui->frame_5      \
               << ui->frame_6 << ui->frame_7 << ui->frame_8 << ui->frame_9 << ui->frame_10     \
               << ui->frame_11 << ui->frame_12 << ui->frame_13 << ui->frame_14 << ui->frame_15 \
               << ui->frame_16 << ui->frame_17 << ui->frame_18 << ui->frame_19 << ui->frame_20;
    label_list << ui->label_1 << ui->label_2 << ui->label_3 << ui->label_4 << ui->label_5      \
               << ui->label_6 << ui->label_7 << ui->label_8 << ui->label_9 << ui->label_10     \
               << ui->label_11 << ui->label_12 << ui->label_13 << ui->label_14 << ui->label_15 \
               << ui->label_16 << ui->label_17 << ui->label_18 << ui->label_19 << ui->label_20;
    /* 初始化顯示 */
    for(int i = 0; i < frame_list.size(); i++)
    {
        frame_list[i]->setText("bottom:"+QString::number(i+1));
        frame_list[i]->setAlignment(Qt::AlignBottom|Qt::AlignHCenter);
    }

    for(int i = 0; i < label_list.size(); i++)
    {
        label_list[i]->setText(QString::number(i+1));
        label_list[i]->setAlignment(Qt::AlignCenter|Qt::AlignHCenter);
        label_list[i]->setStyleSheet("QLabel{font-size:90px;}");
        label_list[i]->setAttribute(Qt::WA_TranslucentBackground);
    }

控件是我在UI中添加的

運行之後如圖

這樣就實現了批量處理同類控件的方法,在程序中Button和Label是用的方法不同,Button方法更適合一次改變萬年不動的屬性,而Label使用的方法是足夠靈活的,你可以直接使用Label_list[i]來控制單個label屬性,Button方法也可以實現,但是會出現不按控件順序添加的情況,所以建議使用Label方法

要查看UI中控件疊加顯示方法,請參考

https://blog.csdn.net/qq_39295354/article/details/104010241

 

2020.01.18更新

使用事件過濾器爲每一個label添加按鈕點擊事件

1.什麼是事件過濾器

事件過濾器是一個接收所有發送到該對象的事件的對象。過濾器可以停止事件,也可以將其轉發給此對象。事件過濾器filterObj通過它的eventFilter()函數接收事件。如果事件應該被過濾(即停止),則eventFilter()函數必須返回true;否則它必須返回false。如果在單個對象上安裝多個事件篩選器,則最先激活最後安裝的篩選器。

2.爲對象安裝事件過濾器

void QObject::installEventFilter(QObject *filterObj)

例如:

monitoredObj->installEventFilter(filterObj);

在本文中,通過遍歷爲每一個label添加事件過濾器

    for(int i = 0; i < label_list.size(); i++)
    {
        label_list[i]->setText(QString::number(i+1));
        label_list[i]->setAlignment(Qt::AlignCenter|Qt::AlignHCenter);
        label_list[i]->setStyleSheet("QLabel{font-size:50px;}");
        label_list[i]->setAttribute(Qt::WA_TranslucentBackground);
        label_list[i]->installEventFilter(this); /* 安裝事件過濾器 */
    }

3. 定義eventFilter()函數接收事件

protected:
    bool eventFilter(QObject *obj, QEvent *event) override;

4. 添加定義,篩選出鼠標左鍵按下事件進行處理

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
    for (int i = 0; i < label_list.size(); i++) {
        if(obj == label_list[i])
        {
            if(event->type() == QEvent::MouseButtonPress)
            {
                QMouseEvent *keyEvent = static_cast<QMouseEvent*>(event);
                if(keyEvent->buttons() == Qt::LeftButton)
                {
                    qDebug() << "label["+QString::number(i+1)+"] is clicked";
                    return true;
                }
            }
            else {
                return false;
            }
        }
    }
    return QMainWindow::eventFilter(obj, event); /* 將事件傳遞給父類 */
}

 

5.效果

/* 打印輸出 */
"label[6] is clicked"
"label[7] is clicked"
"label[8] is clicked"
"label[13] is clicked"
"label[19] is clicked"

6.移除事件過濾器

void QObject::removeEventFilter(QObject *obj)

從該對象中移除事件篩選器對象obj。如果沒有安裝這樣的事件過濾器,請求將被忽略。銷燬此對象時,將自動刪除此對象的所有事件篩選器。刪除事件過濾器總是安全的,即使在事件過濾器激活期間也是如此(即從eventFilter()函數中刪除)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章