Promote QWidget Programmatically

I have a ui file with QProgressBarin QWidget. Moreover, I created my custom runtime component that inherits from QProgressBar. In QT Designer, I can promote a widget QProgressBarinto my custom widget. Is there a way to do this in the cpp widget file instead of using QT Designer? In other words, is there a way to programmatically promote QWidgetin another user widget of the same type (a kind of morphing)?

The following is an example:

class MyProgressBar : public QProgressBar
{
    Q_OBJECT

public:
    explicit CmdProgressWidget(QWidget *parent = 0);
    ~CmdProgressWidget();

    int myCustomFunction();
};

class MyWidgetWithProgress : public QWidget, public Ui::MyWidget
{
    Q_OBJECT

    public:
        MyWidgetWithProgress (QWidget *parent = 0) {setupUi(this);}
        ~MyWidgetWithProgress() {;}

    inline int callMyCustomFunction() {progressBar->myCustomFunction();}
};

A common way to get the code int callMyCustomFunction()to compile is to push the widget progress bar ( QProgressBar) in QT Designer into my custom widget MyProgressBar.

: (, MyWidgetWithProgress setupUi(this);)?

+4
3

cpp widget QT Designer?

: . Qt Designer Xyz.ui, XML . uic .ui ui_Xyz.h. : , , .

, . - (, QProgressBar) , setupUi . , .

.ui . , . , , :

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>256</width>
    <height>40</height>
   </rect>
  </property>
  <layout class="QGridLayout" name="gridLayout">
   <item row="0" column="0">
    <widget class="QProgressBar" name="placeholder">
     <property name="value">
      <number>24</number>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

progressBar, XML. :

<widget class="MyProgressBar" name="placeholder">
 <property name="value">
  <number>24</number>
 </property>
</widget>

<customwidgets>:

<customwidgets>
 <customwidget>
  <class>MyProgressBar</class>
  <extends>QProgressBar</extends>
  <header>myprogressbar.h</header>
 </customwidget>
</customwidgets>

, , .ui , .

:

  • ?

    , . , : , (MyProgressBar) .ui.

    // Would-Be Derived Class
    class MyProgressBar : public QProgressBar {
      int m_var;
    protected:
      void paintEvent(QPaintEvent * ev) {
        QProgressBar::paintEvent(event(ev)); // let the base class paint itself
        QPainter p(this);
        // do some overpainting, etc.
      }
    public:
      void doSomething() {
        m_var = 3;
      }
    };
    
    // Do the same using the base class instead:
    void doSomething(QProgressBar * bar) {
      bar.setProperty("m_var", 3);
    }
    
    void paintEvent(QWidget * w, QPaintEvent * ev) {
      w->event(ev); // let the base class paint itself
      QPainter p(w);
      // do some overpainting, etc.
    }
    
    struct Painter : public QObject {
      bool eventFilter(QObject * obj, QEvent * ev) {
        if (obj->isWidgetType() && ev->type() == QEvent::Paint)
          paintEvent(static_cast<QWidget*>(obj), static_cast<QPaintEvent*>(ev));
        return QObject::eventFilter(obj, ev);
      }
    }
    
    QProgressBar bar;
    bar.installEventFilter(new Painter(&bar));
    
  • .

    // . .

    class Form : public QWidget, private Ui::Form {
      MyProgressBar m_bar;
      ...
    }
    

    .

    void replace(QWidget * & old, QWidget * replacement) {
      auto layout = old->parent()->layout();
      // name the new widget the same
      replacement->setObjectName(old->objectName());
      // swap the widgets and delete the layout item
      delete layout->replaceWidget(old, replacement);
      // delete the old widget
      delete old;
      // don't leave a dangling pointer
      old = nullptr;
    }
    
    Form:: Form(QWidget * parent) :
      QWidget(parent)
    {
      setupUi(this);
      replace(placeholder, &m_bar);
      // you have to manually connect slots for the m_bar widget
    }
    
+1

"" Qt Designer .cpp. , , . ++ : "" .

QWidget*, "" , qobject_cast<>(). , , QWidget "" , NULL.

+1

, , :

QProgressBar* temp = new MyProgressBar(m_widget, CALENDAR_DEL, 30);
m_horizontalLayout->replaceWidget(m_prg, temp);//the most important function replaceWidget()
delete m_prg;//
m_prg = temp;//Qt will release children widgets finally, make sure m_prg point to the temp
-1

Source: https://habr.com/ru/post/1607441/


All Articles