Search code examples
c++qtqt5qt-designer

How do I access a promoted widget's UI elements in code using Qt?


So I created a class DemoPromotedWidget, it inherits from QWidget.

I then created a Widget in the designer, added a label to said widget called DemoLabel, & promoted the widget to class DemoPromotedWidget... Then I moved it to my toolbox, and it's now under "Scratchpad".

Normally, using Qt's designer, I can access ANY elements in the UI file in it's corresponding class file. However, in DemoPromotedWidget I can not.

Is there anyway for me to access DemoLabel inside of DemoPromotedWidget so that I can call something like...

ui->DemoPromotedWidget->setText("Updated Text");

Here is a picture of my UI Designer, with the DemoPromotedWidget already added. https://i.sstatic.net/l7cLX.png

DemoPromotedWidget.h

#ifndef DEMOPROMOTEDWIDGET_H
#define DEMOPROMOTEDWIDGET_H

#include <QWidget>

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

signals:

public slots:
};

#endif // DEMOPROMOTEDWIDGET_H

DemoPromotedWidget.cpp

#include "demopromotedwidget.h"

DemoPromotedWidget::DemoPromotedWidget(QWidget *parent) : QWidget(parent)
{
    // How do I access DemoPromotedWidget->DemoLabel->setText()?????????????????????
}

Here is my mainwindow.ui...

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>711</width>
    <height>418</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <widget class="DemoPromotedWidget" name="DemoPromotedWidget" native="true">
    <property name="geometry">
     <rect>
      <x>160</x>
      <y>60</y>
      <width>381</width>
      <height>191</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">background-color: black;
text-align: center;</string>
    </property>
    <widget class="QLabel" name="DemoLabel">
     <property name="geometry">
      <rect>
       <x>0</x>
       <y>5</y>
       <width>381</width>
       <height>181</height>
      </rect>
     </property>
     <property name="styleSheet">
      <string notr="true">color: white;
text-align: center;</string>
     </property>
     <property name="text">
      <string>DemoLabel</string>
     </property>
     <property name="alignment">
      <set>Qt::AlignCenter</set>
     </property>
    </widget>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menuBar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>711</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QToolBar" name="mainToolBar">
   <attribute name="toolBarArea">
    <enum>TopToolBarArea</enum>
   </attribute>
   <attribute name="toolBarBreak">
    <bool>false</bool>
   </attribute>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <customwidgets>
  <customwidget>
   <class>DemoPromotedWidget</class>
   <extends>QWidget</extends>
   <header>demopromotedwidget.h</header>
   <container>1</container>
  </customwidget>
 </customwidgets>
 <resources/>
 <connections/>
</ui>

Solution

  • You should not use the name of the class with the name of the widget, so the first thing to do is change its name:

    enter image description here

    first option:

    On the other hand that the QLabel this inside the DemoPromotedWidget does not imply that DemoPromotedWidget can access the QLabel and less in the constructor since in that method it is not yet added to the main window, a possible solution is to create an attribute where you can assign it the QLabel:

    demopromotedwidget.h

    #ifndef DEMOPROMOTEDWIDGET_H
    #define DEMOPROMOTEDWIDGET_H
    
    #include <QLabel>
    #include <QWidget>
    
    class DemoPromotedWidget : public QWidget
    {
        Q_OBJECT
    public:
        explicit DemoPromotedWidget(QWidget *parent = nullptr);
        QLabel *getLabel() const;
        void setLabel(QLabel *value);
    private:
        QLabel *label;
    };
    
    #endif // DEMOPROMOTEDWIDGET_H
    

    demopromotedwidget.cpp

    #include "demopromotedwidget.h"
    
    DemoPromotedWidget::DemoPromotedWidget(QWidget *parent) : QWidget(parent)
    {
    
    }
    
    QLabel *DemoPromotedWidget::getLabel() const
    {
        return label;
    }
    
    void DemoPromotedWidget::setLabel(QLabel *value)
    {
        label = value;
        if(label)
            label->setText("some text");
    }
    

    mainwindow.cpp

    ...
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        ui->widget->setLabel(ui->DemoLabel);
    }
    ...
    

    second option:

    Another much simpler way but it can only be done if the widget (QLabel) is added using Qt Designer as in this case using the method showEvent() and findChild():

    demopromotedwidget.h

    #ifndef DEMOPROMOTEDWIDGET_H
    #define DEMOPROMOTEDWIDGET_H
    
    #include <QLabel>
    #include <QWidget>
    
    class DemoPromotedWidget : public QWidget
    {
        Q_OBJECT
    public:
        explicit DemoPromotedWidget(QWidget *parent = nullptr);
    private:
        QLabel *label;
    protected:
        void showEvent(QShowEvent *event);
    };
    
    #endif // DEMOPROMOTEDWIDGET_H
    

    demopromotedwidget.cpp

    #include "demopromotedwidget.h"
    
    DemoPromotedWidget::DemoPromotedWidget(QWidget *parent) : QWidget(parent)
    {
    }
    
    void DemoPromotedWidget::showEvent(QShowEvent *event)
    {
        label = findChild<QLabel *>("DemoLabel");
        if(label)
            label->setText("some text");
        QWidget::showEvent(event);
    }
    

    Update:

    A new approach is that you create a form that is a QWidget and that has a .ui, .h and .cpp:

    enter image description here

    enter image description here

    enter image description here

    As I said create a new class that unlike your initial code has a .ui, then open it with the help of Qt Designer and add the label

    enter image description here

    But it is also a class that you can promote as you did in your first approach.

    enter image description here

    The complete example can be found in the following link