使用 Qt 表单中按顺序命名的 ui 个对象填充数组

Populating array with sequentially named ui objects from Qt form

我有一个 Qt 项目,其中 ui 在 Qt Designer 中创建。 ui 当前包含 16 个 QLabel。我需要一个包含所有 QLabel 的数组。目前我初始化数组:

labels_ = {ui->label0, ui->label1, ui->label2, ui->label3, ui->label4,
           ui->label5, ui->label6, ui->label7, ui->label8, ui->label9,
           ui->label10, ui->label11, ui->label12, ui->label13, ui->label14,
           ui->label15};

我希望以后能够轻松地向 ui 表单添加和删除 QLabel。如果在某个时候我想用 100 个 QLabel 测试程序怎么办?

我发现 Boost.preprocessor 我可以做到这一点:

#define NLABELS 16
#define FILL_ARRAY(z, idx, name) \
    BOOST_PP_CAT(name, idx), 

labels_ = {BOOST_PP_REPEAT(NLABELS, FILL_ARRAY, ui->label)};

但是,我仍然在犹豫这是否是正确的做法。也许 Qt 有一些其他功能来实现这一点?

对我来说似乎是正确的,Qt 没有这方面的功能。

为什么不使用 std::vector<QLabel*> 而不是在创建标签时 push_back 每个标签?可能在成员函数中?

class C
{
    std::vector<QLabel*> labels;

public:
    void createLabel(char const* text)
    {
        QLabel* label; // create it as needed, add it to designated parent

        labels.push_back(label);

        // alternative: create it above without parent
        // and return it here (change signature appropriately)
    }
};

编辑 回复您的评论:

对于在 QT 设计器中使用,自定义标签可能会帮助您:

class MyLabel : public QLabel
{
    static std::vector<MyLabel*> instances;

public:
    MyLabel(/* whatever you need */)
        : QLabel(/*...*/)
    {
        instances.push_back(this);
    }

    ~MyLabel()
    {
        instances.erase
        (
            std::remove(instances.begin(), instances.end(), this),
            instances.end()
        );
    }

    // static begin() and end() functions returning (const_)iterators to your vector
};

QT 设计器也支持(至少在一定程度上)自定义小部件,根据 here

在 Qt 中,您可以使用 findChildren 函数:

    QList<QLabel*> list = this->findChildren<QLabel*>(QRegularExpression("label\d+$"));

这将 return 指向名为 labelXthis 的 QLabels 子项的指针的 QList(其中 X 至少是一位数字)。

LE:通过阅读评论,我假设它没有按您想要的方式排序,因此您可以使用 QCollator 对字符串进行数字排序,如下所示:

QCollator c;
c.setNumericMode(true);

std::sort(list.begin(), list.end(), [&c](QLabel* lhs, QLabel* rhs) {
    if(c.compare(lhs->objectName(), rhs->objectName()) < 0)
        return true;
    return false;
});