加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 以编程方式推广QWidget

发布时间:2020-12-16 06:50:06 所属栏目:百科 来源:网络整理
导读:我在QWidget中有一个带有QProgressBar的ui文件.此外,我已经创建了继承自QProgressBar的自定义进度条组件.在QT Designer中,我可以将QProgressBar小部件提升为我的自定义小部件.有没有办法在widget cpp文件中执行此操作而不是使用QT Designer? 换句话说,有没
我在QWidget中有一个带有QProgressBar的ui文件.此外,我已经创建了继承自QProgressBar的自定义进度条组件.在QT Designer中,我可以将QProgressBar小部件提升为我的自定义小部件.有没有办法在widget cpp文件中执行此操作而不是使用QT Designer?
换句话说,有没有办法以编程方式将QWidget推广到另一个相同类型的自定义窗口小部件(一种变形)?

以下是一个例子:

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()编译的常用方法是在QT Designer中将窗口小部件(QProgressBar)中的进度条提升为我的自定义窗口小部件MyProgressBar.

回到原始问题:有没有办法以编程方式进行(例如在setupUi(this)之后的MyWidgetWithProgress构造函数中;)?

解决方法

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.它的成员类型已设置:您无法以编程方式更改它们,就像您无法以编程方式更改任何其他成员的类型一样.

因此,请在Designer中使用正确的对象类型.如果将某些基类型(比如QProgressBar)提升为您自己的派生类型,则setupUi将创建您的类型的实例.因此,整个问题消失了.

但是您不需要使用Designer更改.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文件,您可以在运行时进行小部件交换.

这有两个主要方面:

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

在许多情况下,您可以在不从基本小部件派生的情况下完成所有操作.是否对你有意义很难说:我不明白为什么你不能在.ui文件中使用正确的类型(MyProgressBar).

// 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
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读