如何在QLayout中找到给定类型的窗口小部件? [英] How to find widgets of a given type in a QLayout?
问题描述
我可以通过这种方式找到 QRadioButton
:
for(int i = 0; i count(); i ++)
{
QRadioButton * r = qobject_cast< QRadioButton *>(ui-> verticalLayout- > itemAt(i) - > widget());
if(r-> isChecked())
//找到了!
}
但我不喜欢这种迭代元素的方式,使用 foreach
构造。
我第一次尝试失败:
foreach(QRadioButton * child,ui-> verticalLayout-> findChildren< QRadioButton *>())
{
if(child-> isChecked())
//找到了!问题是, ui-> verticalLayout->
}
$ b < > findChildren< QRadioButton *>()返回零元素。它也不返回 findChildren< QObject *>()
的元素。有人可以解释这个行为吗?
注意 实验上我认为 有人可能指向我的一个好材料Qt子父的概念?我假设这与访问嵌套对象无关。这是我想要完成的。 根据Kuba Ober的建议,对此问题的回答包含有关另一主题的有用信息,而他的回答澄清了我关于布局的孩子的问题。因此,这不是一个重复的问题。 小部件不是布局的子元素 您可以按照以下方式迭代给定类型的窗口小部件的子项: 如果使用C ++ 11,请使用基于范围的for循环,而不是现在已过时的 布局,你需要一个迭代器适配器的布局。例如: 它的用法如下: 一些初步测试如下: I am able to find the But I don't like this way of iterating over elements and would like to use the Problem is that the Note: the title of this question is almost identical to mine, but it is related to python Qt, and does not contain any helpful information for me. Experimentally I figured that Can someone point me to a good material on Qt child parent concepts? I am assuming that this has nothing to do with accesing nested objects which is what I am trying to accomplish. As suggested by Kuba Ober, the answers to this question contains valuable information on another topic, whereas his answer makes clarification on my question about children of layout. Thus this is not a duplicate question. The widgets are not children of the layout in the sense of being You could iterate a widget's children of a given type as follows: If you're using C++11, you should use the range-based for loop, not the now obsolete To iterate the child widgets managed by a layout, you need an iterator adapter for the layout. For example: It's used as follows: Some rudimentary tests look as follows:
这篇关于如何在QLayout中找到给定类型的窗口小部件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
孩子vs元素?
ui-> verticalLayout-> child()。count()
返回零,其中 ui-> verticalLayout-> count()
verticalLayout
。这意味着 itemAt(i)
和 findChild< QRadioButton *>()
不访问同一个列表。查看 children()
的Qt文档没有帮助我。
编辑
QObject
children - 它们是父窗口小部件的子项。 QWidget
只能是另一个 QWidget
的子级 - 因此你不能期望小部件是布局的子级。虽然新的QWidget(新的QWidget())
工程,新的QWidget(新的QHBoxLayout())
// C ++ 11
for(auto button:findChildren< QRadioButton *>())if(button-> isChecked()){
...
} b
$ b // C ++ 98
Q_FOREACH(QWidget * button,findChildren< QRadioButton *>())
if(button-> isChecked()){
...
}
foreach
或 Q_FOREACH
。
#include< QLayout>
#include< QDebug>
#include< QPointer>
#include< utility>
template< class WT> class IterableLayoutAdapter;
template< typename WT>
class LayoutIterator {
QPointer< QLayout> m_layout;
int m_index;
friend class IterableLayoutAdapter< WT> ;;
LayoutIterator(QLayout * layout,int dir):
m_layout(layout),m_index(dir> 0?-1:m_layout-> count()){
if(dir> 0)++ * this;
}
friend QDebug operator<<(QDebug dbg,const LayoutIterator& it){
return dbg< it.m_layout<< it.m_index;
}
friend void swap(LayoutIterator& a,LayoutIterator& b){
using std :: swap;
swap(a.m_layout,b.m_layout);
swap(a.m_index,b.m_index);
}
public:
LayoutIterator():m_index(0){}
LayoutIterator(const LayoutIterator& o):
m_layout(o.m_layout),m_index (o.m_index){}
LayoutIterator(LayoutIterator&& o){swap(* this,o); }
LayoutIterator& operator =(LayoutIterator o){
swap(* this,o);
return * this;
}
WT * operator *()const {return static_cast< WT *>(m_layout-> itemAt(m_index) - > widget }
const LayoutIterator& operator ++(){
while(++ m_index
return * this;
}
LayoutIterator operator ++(int){
LayoutIterator temp(* this);
++ * this;
return temp;
}
const LayoutIterator& operator - (){
while(!qobject_cast< WT *>(m_layout-> itemAt( - m_index) - > widget())&& m_index>
return * this;
}
LayoutIterator运算符 - (int){
LayoutIterator temp(* this);
- * this;
return temp;
}
bool operator ==(const LayoutIterator& o)const {return m_index == o.m_index; }
bool operator!=(const LayoutIterator& o)const {return m_index!= o.m_index; }
};
template< class WT = QWidget>
class IterableLayoutAdapter {
QPointer< QLayout> m_layout;
public:
typedef LayoutIterator< WT> const_iterator;
IterableLayoutAdapter(QLayout * layout):m_layout(layout){}
const_iterator begin()const {return const_iterator(m_layout,1); }
const_iterator end()const {return const_iterator(m_layout,-1); }
const_iterator cbegin()const {return const_iterator(m_layout,1); }
const_iterator cend()const {return const_iterator(m_layout,-1); }
};
template< class WT = QWidget>
class ConstIterableLayoutAdapter:public IterableLayoutAdapter< const WT> {
public:
ConstIterableLayoutAdapter(QLayout * layout):IterableLayoutAdapter< const WT>(layout){}
};
#include< QApplication>
#include< QLabel>
#include< QHBoxLayout>
int main(int argc,char * argv){
QApplication app(argc,argv);
tests();
QWidget a,b1,b3;
QLabel b2;
QHBoxLayout l(& a);
l.addWidget(& b1);
l.addWidget(& b2);
l.addWidget(& b3);
//将所有窗口小部件类型作为常量迭代
qDebug()<< all,range-for;
for(auto widget:ConstIterableLayoutAdapter<>(& l))qDebug()<<小部件
qDebug()<< all,Q_FOREACH;
Q_FOREACH(const QWidget * widget,ConstIterableLayoutAdapter<>(& l))qDebug()<小部件
//仅迭代标签
qDebug()<< labels,range-for;
for(auto label:IterableLayoutAdapter< QLabel>(& l))qDebug()<标签;
qDebug()<< labels,Q_FOREACH;
Q_FOREACH(QLabel * label,IterableLayoutAdapter< QLabel>(& l))qDebug()<标签;
}
void tests(){
QWidget a,b1,b3;
QLabel b2;
QHBoxLayout l(& a);
IterableLayoutAdapter<> l0(& l);
auto i0 = l0.begin();
qDebug()<< i0; Q_ASSERT(i0 == l0.begin()&& i0 == l0.end());
l.addWidget(& b1);
l.addWidget(& b2);
l.addWidget(& b3);
IterableLayoutAdapter<> l1(& l);
auto i1 = l1.begin();
qDebug()<< i1; Q_ASSERT(i1 == l1.begin()&& i1!= l1.end());
++ i1; qDebug()<< i1; Q_ASSERT(i1!= l1.begin()&& i1!= l1.end());
++ i1; qDebug()<< i1; Q_ASSERT(i1!= l1.begin()&& i1!= l1.end());
++ i1; qDebug()<< i1; Q_ASSERT(i1!= l1.begin()&& i1 == l.end());
--i1; qDebug()<< i1; Q_ASSERT(i1!= l1.begin()&& i1!= l1.end());
--i1; qDebug()<< i1; Q_ASSERT(i1!= l1.begin()&& i1!= l1.end());
--i1; qDebug()<< i1; Q_ASSERT(i1 == l1.begin()&& i1!= l1.end());
IterableLayoutAdapter< QLabel> l2(& l);
auto i2 = l2.begin();
qDebug()<< i2; Q_ASSERT(i2 == l2.begin()&& i2!= l2.end());
++ i2; qDebug()<< i2; Q_ASSERT(i2!= l2.begin()& i2 == l2.end());
--i2; qDebug()<< i2; Q_ASSERT(i2 == l2.begin()&& i2!= l2.end());
}
QRadioButton
this way:for(int i = 0; i < ui->verticalLayout->count(); i++)
{
QRadioButton* r = qobject_cast<QRadioButton*>(ui->verticalLayout->itemAt(i)->widget());
if(r->isChecked())
//found it!
}
foreach
construct.
My first attempt fails:foreach(QRadioButton* child, ui->verticalLayout->findChildren<QRadioButton*>())
{
if(child->isChecked())
//found it!
}
ui->verticalLayout->findChildren<QRadioButton*>()
returns zero elements. It also returns no elements with findChildren<QObject*>()
. Can someone please explain this behaviour?Children vs elements?
ui->verticalLayout->children().count()
returns zero where as ui->verticalLayout->count()
returns the number of elements I have in the verticalLayout
. This implies that itemAt(i)
and findChild<QRadioButton*>()
do not access the same list. Looking at the Qt documentation on children()
did not help me.Edit
QObject
children - they are children of the parent widget. A QWidget
can only be a child of another QWidget
- thus you can't ever expect widgets to be layout's children. While new QWidget(new QWidget())
works, new QWidget(new QHBoxLayout())
won't compile.// C++11
for (auto button : findChildren<QRadioButton*>()) if (button->isChecked()) {
...
}
// C++98
Q_FOREACH (QWidget * button, findChildren<QRadioButton*>())
if (button->isChecked()) {
...
}
foreach
or Q_FOREACH
.#include <QLayout>
#include <QDebug>
#include <QPointer>
#include <utility>
template<class WT> class IterableLayoutAdapter;
template<typename WT>
class LayoutIterator {
QPointer<QLayout> m_layout;
int m_index;
friend class IterableLayoutAdapter<WT>;
LayoutIterator(QLayout * layout, int dir) :
m_layout(layout), m_index(dir>0 ? -1 : m_layout->count()) {
if (dir > 0) ++*this;
}
friend QDebug operator<<(QDebug dbg, const LayoutIterator & it) {
return dbg << it.m_layout << it.m_index;
}
friend void swap(LayoutIterator& a, LayoutIterator& b) {
using std::swap;
swap(a.m_layout, b.m_layout);
swap(a.m_index, b.m_index);
}
public:
LayoutIterator() : m_index(0) {}
LayoutIterator(const LayoutIterator & o) :
m_layout(o.m_layout), m_index(o.m_index) {}
LayoutIterator(LayoutIterator && o) { swap(*this, o); }
LayoutIterator & operator=(LayoutIterator o) {
swap(*this, o);
return *this;
}
WT * operator*() const { return static_cast<WT*>(m_layout->itemAt(m_index)->widget()); }
const LayoutIterator & operator++() {
while (++m_index < m_layout->count() && !qobject_cast<WT*>(m_layout->itemAt(m_index)->widget()));
return *this;
}
LayoutIterator operator++(int) {
LayoutIterator temp(*this);
++*this;
return temp;
}
const LayoutIterator & operator--() {
while (!qobject_cast<WT*>(m_layout->itemAt(--m_index)->widget()) && m_index > 0);
return *this;
}
LayoutIterator operator--(int) {
LayoutIterator temp(*this);
--*this;
return temp;
}
bool operator==(const LayoutIterator & o) const { return m_index == o.m_index; }
bool operator!=(const LayoutIterator & o) const { return m_index != o.m_index; }
};
template <class WT = QWidget>
class IterableLayoutAdapter {
QPointer<QLayout> m_layout;
public:
typedef LayoutIterator<WT> const_iterator;
IterableLayoutAdapter(QLayout * layout) : m_layout(layout) {}
const_iterator begin() const { return const_iterator(m_layout, 1); }
const_iterator end() const { return const_iterator(m_layout, -1); }
const_iterator cbegin() const { return const_iterator(m_layout, 1); }
const_iterator cend() const { return const_iterator(m_layout, -1); }
};
template <class WT = QWidget>
class ConstIterableLayoutAdapter : public IterableLayoutAdapter<const WT> {
public:
ConstIterableLayoutAdapter(QLayout * layout) : IterableLayoutAdapter<const WT>(layout) {}
};
#include <QApplication>
#include <QLabel>
#include <QHBoxLayout>
int main(int argc, char ** argv) {
QApplication app(argc, argv);
tests();
QWidget a, b1, b3;
QLabel b2;
QHBoxLayout l(&a);
l.addWidget(&b1);
l.addWidget(&b2);
l.addWidget(&b3);
// Iterate all widget types as constants
qDebug() << "all, range-for";
for (auto widget : ConstIterableLayoutAdapter<>(&l)) qDebug() << widget;
qDebug() << "all, Q_FOREACH";
Q_FOREACH (const QWidget * widget, ConstIterableLayoutAdapter<>(&l)) qDebug() << widget;
// Iterate labels only
qDebug() << "labels, range-for";
for (auto label : IterableLayoutAdapter<QLabel>(&l)) qDebug() << label;
qDebug() << "labels, Q_FOREACH";
Q_FOREACH (QLabel * label, IterableLayoutAdapter<QLabel>(&l)) qDebug() << label;
}
void tests() {
QWidget a, b1, b3;
QLabel b2;
QHBoxLayout l(&a);
IterableLayoutAdapter<> l0(&l);
auto i0 = l0.begin();
qDebug() << i0; Q_ASSERT(i0 == l0.begin() && i0 == l0.end());
l.addWidget(&b1);
l.addWidget(&b2);
l.addWidget(&b3);
IterableLayoutAdapter<> l1(&l);
auto i1 = l1.begin();
qDebug() << i1; Q_ASSERT(i1 == l1.begin() && i1 != l1.end());
++i1; qDebug() << i1; Q_ASSERT(i1 != l1.begin() && i1 != l1.end());
++i1; qDebug() << i1; Q_ASSERT(i1 != l1.begin() && i1 != l1.end());
++i1; qDebug() << i1; Q_ASSERT(i1 != l1.begin() && i1 == l1.end());
--i1; qDebug() << i1; Q_ASSERT(i1 != l1.begin() && i1 != l1.end());
--i1; qDebug() << i1; Q_ASSERT(i1 != l1.begin() && i1 != l1.end());
--i1; qDebug() << i1; Q_ASSERT(i1 == l1.begin() && i1 != l1.end());
IterableLayoutAdapter<QLabel> l2(&l);
auto i2 = l2.begin();
qDebug() << i2; Q_ASSERT(i2 == l2.begin() && i2 != l2.end());
++i2; qDebug() << i2; Q_ASSERT(i2 != l2.begin() && i2 == l2.end());
--i2; qDebug() << i2; Q_ASSERT(i2 == l2.begin() && i2 != l2.end());
}