c++ 遍历QButtonGroup::buttons导致崩溃

odopli94  于 2024-01-09  发布在  其他
关注(0)|答案(1)|浏览(334)

这是我的符号定义:

  1. auto box1=new QCheckBox;
  2. box1->setText("choice1");
  3. auto box2=new QCheckBox;
  4. box2->setText("choice2")
  5. QPushButton* button=new QPushButton;
  6. connect(button,&QPushButton::clicked,this,&Widget::onClicked);
  7. auto group=new QButtonGroup;
  8. group->setExclusive(false);
  9. group->addButton(box1);
  10. group->addButton(box2);

个字符
buttons()调用将返回一个QList<QAbstractButton *>
我尝试使用onClicked插槽来遍历列表并做一些事情。
如果我添加了未注解的代码段,程序会崩溃。我调试了它,发现它循环了三次,但实际上只添加了两个元素,第三次循环会使程序崩溃。
如果我删除注解掉的代码,它就可以工作了。
我想知道为什么第一种编写方式,即没有注解掉的代码会导致错误。

falq053o

falq053o1#

正如我在评论中所解释的(我自己没有检查过,但@musicamente证实了),std::for_each(group->buttons().begin(), group->buttons().end(), [...])创建了两个单独的列表(通过复制构造),其中的end()迭代器是不同的;重要的是,你不能从前者的begin()迭代器到达后者的end()迭代器,这会导致std::for_each一直循环到末尾。
这个问题不会发生在基于范围的循环中(这更容易阅读到顶部)。当我在这里的时候,我将使用toggle方法来切换复选框的checkstate:

  1. void Widget::onClicked()
  2. {
  3. for (auto checkbox: group->buttons())
  4. button->toggle();
  5. }

字符串
在一个单独的说明中,除非你有一个特定的原因来做你在你的问题中提出的方式,例如@musicamente下面的评论(但即使这样,我宁愿在运行时创建一个新的复选框时创建一个连接+当对象被删除时断开连接是自动的),将按钮连接到许多复选框的正确方法是:

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


这节省了声明void Widget::onClicked()
根据Widget类的其他部分,它甚至可以在没有group的情况下工作,以这种方式:

  1. [...]
  2. QPushButton* button=new QPushButton;
  3. for (auto checkbox : findChildren<QCheckBox>(QString()))
  4. QObject::connect(button, &QAbstractButton::clicked, checkbox, &QAbstractButton::toggle);

展开查看全部

相关问题