如果在派生的 QWidget 中加载 QUiLoader 小部件不显示

Posted

技术标签:

【中文标题】如果在派生的 QWidget 中加载 QUiLoader 小部件不显示【英文标题】:QUiLoader widget not showing if loaded in derived QWidget 【发布时间】:2016-06-30 18:35:25 【问题描述】:
Widget::Widget(QWidget *parent) : QWidget(parent) 
    file.open(QFile::ReadOnly);
    QWidget *w = loader.load(&file);
//    MyWidget *w = new MyWidget(loader.load(&file));
    vLayout.addWidget(w);
    file.close();        
    vLayout.addWidget(&bt);

上面的代码生成了上面的图像。但是我想对刚刚加载的小部件做点什么,这就是我从QWidget 派生MyWidget 的原因。而且好像有问题。

如果我将QWidget 替换为MyWidget,那么它就不会再在那里显示了。下面的代码生成下面的图像。

Widget::Widget(QWidget *parent) : QWidget(parent) 
    file.open(QFile::ReadOnly);
//    QWidget *w = loader.load(&file);
    MyWidget *w = new MyWidget(loader.load(&file));
    vLayout.addWidget(w);
    file.close();        
    vLayout.addWidget(&bt);

在哪里MyWidget

// mywidget.h
#include <QWidget>

class MyWidget : public QWidget 
    Q_OBJECT
public:
    explicit MyWidget(QWidget *parent = nullptr);
;

// mywidget.cpp
#include "mywidget.h"    
#include <QDebug>

MyWidget::MyWidget(QWidget *parent) : QWidget(parent) 
    qDebug() << "do something here";

问题 1:为什么小部件(组框)没有显示在那里?如何让它出现?

好的,感谢@KubaOber,问题 1 已完成。现在我想访问untitled.ui里面的小部件,我试过了:

MyWidget::MyWidget(QWidget *parent) : QWidget(parent) 
    foreach (QLabel *label, parent->findChildren<QLabel*>())
        if(label->objectName().contains("Value"))
            qDebug() << "label" << label;


但它什么也没返回。相反,在loader.load(&amp;file, vLayoutWidget)) 中传递一个父级可以使untitled.ui 小部件可用,但也会使vLayoutWidget 的内容失效。我想问题是应该在loader.load()) 中作为父级传递什么?

【问题讨论】:

理想情况下,您应该以this one 的风格创建一个独立的测试用例。 请发布一个新问题,而不是编辑成一个旧问题。 你指的是哪个旧的? 您不能在MyWidget 的构造函数中迭代任何内容,因为此时它还没有子级。再次,请绝对发布完整测试用例。我不得不假设其余代码的外观。如果没有一段简单的代码可以在不搞乱主项目的情况下进行试验,您的生活也会变得更加艰难。了解如何使用 Qt Creator 快速创建测试项目。您可以使用my simple qmake project template 来帮助解决这个问题。 【参考方案1】:

您使用加载程序的方式并不意味着“使用QUiLoader 加载MyWidget

MyWidget *w = new MyWidget(loader.load(&file));

您在上面所做的是初始化一个MyWidget,该MyWidget 具有加载程序作为父项 加载的任何内容。然后,您可以通过将 w 添加到布局中来立即重新设置其父级,从而有效地丢弃加载器已加载的任何内容。

您需要告诉加载器要将已加载的小部件添加到哪个父级,当然要注意MyWidget 不需要动态分配:

auto w = new MyWidget;
loader.load(&file, w);

以下是它放在一起时的样子:

class Widget : public QWidget 
  Q_OBJECT
  QVBoxLayout m_layoutthis;
  MyWidget m_myWidget;
  QVBoxLayout m_myLayout&m_myWidget;
public:
  explicit Widget(QIODevice * source, QWidget * parent = nullptr) : 
    QWidgetparent
  
    auto loaded = QUiLoader.load(source, &m_myWidget);
    m_layout.addWidget(&m_myWidget);
    m_myLayout.addWidget(loaded);
  
;

如果您的 ui 文件的***小部件是 MyWidget,那么您需要让加载程序知道如何实例化它 - 有关详细信息,请参阅 this answer。然后你可以这样写:

class Widget : public QWidget 
  Q_OBJECT
  QVBoxLayout m_layoutthis;
  MyWidget * m_myWidget;
public:
  explicit Widget(QWidget * loaded, QWidget * parent = nullptr) : 
    QWidgetparent,
    m_myWidgetqobject_cast<MyWidget*>(loaded)
  
    m_layout.addWidget(m_myWidget);
  
;

...
MyUiLoader loader
auto loaded = loader.load(...);
Widget widgetloaded;
...

【讨论】:

以上是关于如果在派生的 QWidget 中加载 QUiLoader 小部件不显示的主要内容,如果未能解决你的问题,请参考以下文章

在 django 中加载带有变量名的静态文件

向QGraphicsScene中加入控件

在每个类型继承方案的表中加载 EF 导航属性

将 QWidget 或其他 QWidget 派生控件添加到 QWindow

漫谈QWidget及其派生类(三)

QWidget 派生类不可见