有没有办法在小部件 cpp 文件中执行此操作,而不是使用 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>
item:
<customwidgets>
<customwidget>
<class>MyProgressBar</class>
<extends>QProgressBar</extends>
<header>myprogressbar.h</header>
</customwidget>
</customwidgets>
如果您实际上打算有一个不正确的.ui
文件中,您可以在运行时进行小部件交换。
这主要有两个方面:
-
您真的需要自定义类型吗?
在许多情况下,您无需从基本小部件派生即可完成所有操作。很难说它对你是否有意义:我不明白为什么你不能使用正确的类型(MyProgressBar
) 在你的.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));
-
正在做替换。
您需要通过正确类型的指针/引用/值来访问小部件。理想情况下,直接按值存储新的小部件。
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
}