以编程方式推广QWidget [英] Programmatically promote QWidget

查看:148
本文介绍了以编程方式推广QWidget的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在 QWidget 中有 QProgressBar 的ui文件。此外,我创建了我的自定义进度条组件继承自 QProgressBar 。在QT Designer中,我可以将 QProgressBar 小部件提升到我的自定义小部件。有没有办法在窗口小部件cpp文件而不是使用QT设计器?
换句话说,有没有办法以编程方式将 QWidget 提升为同一类型的另一个自定义窗口小部件(一种变形)

I have an ui file with a QProgressBar in a QWidget. Moreover, I've created my custom progress bar component that inherits from QProgressBar. In QT Designer, I can promote the QProgressBar widget to my custom widget. Is there a way to do this in the widget cpp file instead of using QT Designer? In other words, is there a way to programmatically promote a QWidget into an another custom widget of the same type (a sort of morphing)?

下面是一个例子:

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();}
};

获取代码的常用方法 int callMyCustomFunction() compile是在Qt Designer中宣传的小部件中的进度条( QProgressBar )到我的自定义小部件 MyProgressBar

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

回到原来的问题:是否有一种编程方式(例如 MyWidgetWithProgress c $ c> setupUi(this); )?

Back to original question: is there a way to do it programmatically (e.g. in the MyWidgetWithProgress constructor after setupUi(this);)?

推荐答案


有没有办法在窗口小部件的cpp文件而不是使用QT设计器?

Is there a way to do this in the widget cpp file instead of using QT Designer?

一般来说:不。 Qt Designer生成 Xyz.ui 文件,对象树和对象属性的简单XML描述。 uic 代码生成器采用 .ui 文件并生成 ui_Xyz.h 。其成员的类型设置为:您无法以编程方式更改它们,就像您无法以编程方式更改任何其他成员的类型。

Generally speaking: no. Qt Designer generates a Xyz.ui file, a simple XML description of the object tree and object properties. The uic code generator takes that .ui file and generates ui_Xyz.h. The types of its members are set: you cannot programmatically change them, just as you can't programmatically change the type of any other member.

因此,请使用正确的类型的对象在设计器中。如果您将一些基本类型(比如 QProgressBar )提升为您自己的派生类型,则 setupUi 你的类型。因此,整个问题消失。

So, use the correct type of the object in the Designer. If you promote some base type (say a QProgressBar) to your own derived type, the setupUi will create an instance of your type. Thus, the whole problem disappears.

但您不需要使用Designer更改 .ui 文件。您可以手动更改它来提升您需要的小部件。假设我们从一个具有进度条的简单小部件开始:

But you don't need to change the .ui file using Designer. You can trivially change it manually to promote the widgets you need. Suppose we start with a simple widget that has a progress bar in it:

<?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文件进行两个更改。首先,更改项本身的类型:

To change the type of the progressBar item, you have to make two changes to the XML file. First, change the type of the item itself:

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

然后将您的类型添加到< customwidgets> item:

Then add your type to the <customwidgets> item:

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

如果您打算实际上有一个不正确的 .ui 文件,您可以在运行时进行窗口小部件交换。

If you intend to, in effect, have an incorrect .ui file, you can do the widget swap at runtime.

有两个主要方面:


  1. 你真的需要一个自定义类型吗?

  1. Do you actually need a custom type?

在很多情况下,窗口小部件。是否有意义你很难说:我不明白为什么你不能在中使用正确的类型( MyProgressBar )。 ui 文件。

In many cases, you can do everything without deriving from the base widget. Whether it makes sense for you is hard to tell: I don't understand why you can't use the proper type (MyProgressBar) in your .ui file.

// 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));


  • Doing the replacement.

    您需要通过正确类型的指针/引用/值访问窗口小部件。

    You need access to the widget through a pointer/reference/value of a correct type. Ideally, store the new widget directly by value.

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

    然后,在其布局中替换占位符小部件

    Then, replace the placeholder widget in its layout with an instance of the proper type.

    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
    }
    


  • 这篇关于以编程方式推广QWidget的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆