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()函数中删除)。

发布了17 篇原创文章 · 获赞 8 · 访问量 2641

猜你喜欢

转载自blog.csdn.net/qq_39295354/article/details/104014544