【问题标题】:Qt get children from layoutQt从布局中获取孩子
【发布时间】:2011-05-03 04:43:56
【问题描述】:

我尝试隐藏布局中的所有小部件。但看起来findChildren 没有 为布局工作。

这是我的示例代码:

QLayout * layout = widget -> findChild<QLayout *> (layoutName);
QList<QWidget *> list = layout -> findChildren<QWidget *> ();

cout << list.size() << endl;

size 为 0,但在此布局中,我有一些小部件。 但是,如果我尝试从父小部件获取小部件,相同的代码可以正常工作。

如何从适当的布局中获取它们?

【问题讨论】:

    标签: c++ qt qt4 qt-designer


    【解决方案1】:

    您是否尝试过 children() 方法而不是 findChildren() ?也许您从 widget -&gt; findChild&lt;QLayout *&gt; (layoutName) 方法中得到了一个“糟糕”的布局。尝试在创建布局后立即找到孩子 - 这样您就可以确定布局是正确的。这样做您将能够确定哪个功能出错。

    【讨论】:

    • 是的,我尝试了 children(),但没有任何运气。创建后我无法检查,因为它是从 .ui 加载的...对于小部件工作正常...问题仅与布局有关..
    【解决方案2】:

    布局不会将自身“注入”到父子树中,因此小部件保持(直接)其父小部件的子级。

    您可以改用QLayout::count()QLayout::itemAt()

    【讨论】:

    • 关键是一个布局可以成为一个小部件的子级(因为它们都继承了QObject),但一个小部件不能成为一个布局的子级。一个小部件必须有另一个小部件作为父级,并且QLayout 不继承QWidget。布局将它们包含的每个项目包装在 QLayoutItem 中,因此需要一组不同的 API 来访问底层对象。
    • 很糟糕,这条评论已经有四年历史了。即使在今天,Qt 使 QLayout 跟踪其中的小部件的方式是私有 d_ptr 及其列表属性。没有公共 API...
    【解决方案3】:

    由于布局不是小部件层次结构的一部分,因此必须从父级查询小部件,然后可以使用 indexOf 来查看它是否属于及其位置

      QLayout * top_l= layout(); // The parent widgets layout
       // Find your layout that you want to search inside
       QHBoxLayout * hbox = top_l->findChild<QHBoxLayout*>(QString("horizontalLayout_2"));
        if (hbox != 0) {
            std::cout << "Found horizontalLayout_2!"<<std::endl;
            QPushButton * st = findChild<QPushButton*>(QString("startButton"));
    
            if (st != 0) {
                std::cout << "Found startButton in top level widget"<<std::endl;
                int idx = hbox->indexOf(st);
                if (idx >=0) {
                    std::cout << "Found startButton in hbox layout at location : "
                              <<idx<<std::endl;
                }
            }
        };
    

    【讨论】:

      【解决方案4】:

      您可以简单地迭代布局的项目,使用itemAt(),然后测试项目是否是一个小部件:

      for (int i = 0; i < gridLayout->count(); ++i)
      {
        QWidget *widget = gridLayout->itemAt(i)->widget();
        if (widget != NULL)
        {
          widget->setVisible(false);
        }
        else
        {
          // You may want to recurse, or perform different actions on layouts.
          // See gridLayout->itemAt(i)->layout()
        }
      }
      

      【讨论】:

        【解决方案5】:

        已经很晚了,但是如果有人像我一样在这里找到,这是我的解决方案: 我尝试了@braggPeaks 的答案(它与@Frank Osterfeld 的答案相同)但它失败了。然后我像这样修改它,它就像一个魅力。 (我不知道它为什么会起作用,因为我的布局没有空项目,但我仍然必须检查它是否有。)

        for (int i = 0; i < this->layout->count(); ++i) {
            QWidget *w = this->layout->itemAt(i)->widget();
            if(w != NULL)
                w->setVisible(false);
        }
        

        【讨论】:

        【解决方案6】:

        回复一个旧帖子,但我想要一种简单的方法来禁用布局或任何子布局中包含的所有小部件。这适用于我的目的:

        void setEnabledWidgetsInLayout(QLayout *layout, bool enabled)
        {
           if (layout == NULL)
              return;
        
           QWidget *pw = layout->parentWidget();
           if (pw == NULL)
              return;
        
           foreach(QWidget *w, pw->findChildren<QWidget*>())
           {
              if (isChildWidgetOfAnyLayout(layout,w))
                 w->setEnabled(enabled);
           }
        }
        
        bool isChildWidgetOfAnyLayout(QLayout *layout, QWidget *widget)
        {
           if (layout == NULL or widget == NULL)
              return false;
        
           if (layout->indexOf(widget) >= 0)
              return true;
        
           foreach(QObject *o, layout->children())
           {
              if (isChildWidgetOfAnyLayout((QLayout*)o,widget))
                 return true;
           }
        
           return false;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-01-25
          • 2018-07-16
          • 2012-10-03
          • 2022-10-09
          • 1970-01-01
          • 1970-01-01
          • 2020-04-05
          相关资源
          最近更新 更多