以编程方式推广QWidget
Programmatically promote QWidget
我在QWidget
中有一个QProgressBar
的ui文件。此外,我已经创建了从QProgressBar
继承的自定义进度条组件。在QT设计器中,我可以将QProgressBar
小部件提升到我的自定义小部件。有没有办法做到这一点,在小部件的cpp文件,而不是使用QT设计器?换句话说,是否有一种方法可以通过编程方式将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
构造函数)?
有办法做到这一点在小部件cpp文件,而不是使用QT设计器?
一般来说:没有。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
文件,您可以在运行时进行小部件交换。
有两个主要方面:
你真的需要自定义类型吗?
在许多情况下,您可以在不从基本小部件派生的情况下完成所有操作。这对你来说是否有意义很难判断:我不明白为什么你不能在你的
.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 }
Qt Designer中的"promote"操作改变了小部件的实际类型,并在.cpp文件中使用了被提升的小部件类。编译器永远不会将原始的、未提升的类名视为小部件的类型。在c++中,您必须做同样的事情:将小部件的类型更改为所谓的"提升"类型。
你可以,如果你有一个任意的QWidget*
,通过使用qobject_cast<>()
将它转换成你的"提升"类型。这只有在您知道指向的QWidget
是您的"提升"类的实例化时才会起作用,否则强制转换将返回NULL
。
- 如果我只是不访问queue_front节点的子节点,而是将它们推到队列中呢?还是BFS吗
- 如何在c++中为模板函数实例创建快捷方式
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错
- 没有为自己的结构调用列表推回方法
- 在c代码之间共享数据的最佳方式
- 在C++中将函数压缩为两种方式
- 以螺旋方式打印矩阵的程序.(工作不好)
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- 我应该实现右值推送功能吗?我应该使用std::move吗
- 创建引用向量的优雅方式
- Constexpr替代了新的放置方式,可以让内存中的对象保持未初始化状态
- 使用QQuickFramebufferObject时同步数据的最佳方式是什么
- 尝试将unique_ptrs推送到向量时使用纯虚拟函数错误
- 不同/较旧的处理器运行c++代码的方式是否不同
- 将 std::array 推回 std::vector N 次的优雅方式
- 指针的c++矢量以不同的方式进行反推
- 声明继承的模板化对象并将它们推回矢量 - 优雅的方式
- 以编程方式推广QWidget
- 为什么助推构造器的工作方式如此不同?
- 推入堆栈的另一种方式