迭代 QButtonGroup::buttons 会导致崩溃

问题描述 投票:0回答:1

这是我的符号定义:

auto box1=new QCheckBox;
box1->setText("choice1");
auto box2=new QCheckBox;
box2->setText("choice2")
QPushButton* button=new QPushButton;
connect(button,&QPushButton::clicked,this,&Widget::onClicked);
auto group=new QButtonGroup;
group->setExclusive(false);
group->addButton(box1);
group->addButton(box2);
void Widget::onClicked()
{
    std::for_each(group->buttons().begin(),group->buttons().end(),[](QAbstractButton* button){
            button->setChecked(!button->isChecked());
    });
    /*
    QList<QAbstractButton *> buttons=group->buttons();
    std::for_each(buttons.begin(),buttons.end(),[](QAbstract* button){
    button->setChecked(!button->isChecked());
    });
    */
}

buttons()
调用将返回
QList<QAbstractButton *>

我尝试使用

onClicked
插槽来迭代列表并执行某些操作。

如果我添加未注释的代码部分,程序就会崩溃。我调试了一下,发现循环了三次,但实际上只添加了两个元素,第三次循环就会导致程序崩溃。

如果我删除注释掉的代码段,它就可以工作。

我想知道为什么第一种写法,即没有注释掉的代码,会导致错误。

c++ loops qt iterator qbuttongroup
1个回答
1
投票

正如我在评论中解释的那样(我自己没有检查过,但得到了 @musicamente 的确认),

std::for_each(group->buttons().begin(), group->buttons().end(), [...])
创建了 2 个单独的列表(通过复制构造),其中
end()
迭代器是不同的;重要的是,您无法从前者的
end()
迭代器到达后者的
begin()
迭代器,这会导致
std::for_each
不断循环到末尾。

使用基于范围的循环就不会出现此问题(这更容易阅读顶部)。当我这样做时,我将使用

toggle
方法来切换复选框的选中状态:

void Widget::onClicked()
{
    for (auto checkbox: group->buttons())
        button->toggle();
}

在一个单独的说明中,除非您有特定的原因按照您在问题中提出的方式执行此操作,例如下面@musicamente的评论(但即便如此,我宁愿每次在运行时创建一个新复选框时都创建一个连接-删除对象时自动断开连接),将按钮连接到许多复选框的正确方法是:

[...]
QPushButton* button=new QPushButton;
auto group=new QButtonGroup;
group->setExclusive(false);
group->addButton(box1);
group->addButton(box2);
for (auto checkbox : group->buttons())
    QObject::connect(button, &QAbstractButton::clicked, checkbox, &QAbstractButton::toggle);

这样可以节省声明

void Widget::onClicked()

取决于

Widget
类的其余部分,它甚至可以在没有
group
的情况下工作,以这种方式:

[...]
QPushButton* button=new QPushButton;
for (auto checkbox : findChildren<QCheckBox>(QString()))
    QObject::connect(button, &QAbstractButton::clicked, checkbox, &QAbstractButton::toggle);
© www.soinside.com 2019 - 2024. All rights reserved.