QUiLoader:需要使用自定义小部件加载 .ui 文件的 ui 备注?
QUiLoader: requirements for loading .ui file with custom widgets?
我使用 Qt5-Designer 创建了一个 UI,我通过调用
在运行时加载它
QUiLoader().load(qfile_object, this);
像魅力一样工作,但现在我已经将一些 QLabel
元素提升为小部件 class MyQLabel
派生自 QLabel
.
当我现在尝试加载 UI 时,我收到每个升级小部件的警告:
"QFormBuilder was unable to create a custom widget of the class 'MyQLabel'; defaulting to base class 'QLabel'."
class 看起来像这样:
class MyQLabel : public QLabel {
Q_OBJECT
public:
MyQLabel(QWidget *parent = nullptr) : QLabel(parent) {}
};
它已自动 moc
并链接到我的可执行文件。
我觉得在尝试使用它之前我必须以某种方式告诉 QUiLoader
我的 class 但我不知道如何..
我必须为此创建一个插件吗?有没有办法重现,要QUiLoader
做什么检查呢?
您需要创建自己的 QUiLoader
派生版本,并提供可以创建您的小部件的工厂方法 QUiLoader::createWidget
的实现。
您可以将其分解为由 QUiLoader
加载的插件。它必须实现 QDesignerCustomWidgetInterface
instance. See the Custom Widget Plugin Example 以获得完整的插件示例。
// https://github.com/KubaO/Whosebugn/tree/master/questions/uiloader-custom-37775472
#include <QtUiTools>
#include <QtWidgets>
const char uiData[] =
"<ui version=\"4.0\"><class>Widget</class><widget class=\"MyWidget\" name=\"Widget\">\n"
"<property name=\"windowTitle\" ><string>Widget</string></property>\n"
"</widget><pixmapfunction></pixmapfunction><resources/><connections/>\n"
"</ui>";
class MyWidget : public QLabel
{
Q_OBJECT
bool m_closed = false;
public:
MyWidget(QWidget* parent = 0) : QLabel("This is MyWidget", parent) {}
bool isClosed() const { return m_closed; }
void closeEvent(QCloseEvent *) Q_DECL_OVERRIDE { m_closed = true; }
};
class MyUiLoader : public QUiLoader {
public:
MyUiLoader(QObject * parent = 0) : QUiLoader(parent) {}
QWidget * createWidget(const QString & className, QWidget * parent = 0,
const QString & name = QString()) {
if (className == "MyWidget") {
MyWidget * w = new MyWidget(parent);
w->setObjectName(name);
return w;
}
return QUiLoader::createWidget(className, parent, name);
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QBuffer buf;
buf.setData(uiData, sizeof(uiData));
MyUiLoader uiLoader;
auto uiMain = qobject_cast<MyWidget*>(uiLoader.load(&buf));
uiMain->show();
return app.exec();
}
#include "main.moc"
我使用 Qt5-Designer 创建了一个 UI,我通过调用
在运行时加载它QUiLoader().load(qfile_object, this);
像魅力一样工作,但现在我已经将一些 QLabel
元素提升为小部件 class MyQLabel
派生自 QLabel
.
当我现在尝试加载 UI 时,我收到每个升级小部件的警告:
"QFormBuilder was unable to create a custom widget of the class 'MyQLabel'; defaulting to base class 'QLabel'."
class 看起来像这样:
class MyQLabel : public QLabel {
Q_OBJECT
public:
MyQLabel(QWidget *parent = nullptr) : QLabel(parent) {}
};
它已自动 moc
并链接到我的可执行文件。
我觉得在尝试使用它之前我必须以某种方式告诉 QUiLoader
我的 class 但我不知道如何..
我必须为此创建一个插件吗?有没有办法重现,要QUiLoader
做什么检查呢?
您需要创建自己的 QUiLoader
派生版本,并提供可以创建您的小部件的工厂方法 QUiLoader::createWidget
的实现。
您可以将其分解为由 QUiLoader
加载的插件。它必须实现 QDesignerCustomWidgetInterface
instance. See the Custom Widget Plugin Example 以获得完整的插件示例。
// https://github.com/KubaO/Whosebugn/tree/master/questions/uiloader-custom-37775472
#include <QtUiTools>
#include <QtWidgets>
const char uiData[] =
"<ui version=\"4.0\"><class>Widget</class><widget class=\"MyWidget\" name=\"Widget\">\n"
"<property name=\"windowTitle\" ><string>Widget</string></property>\n"
"</widget><pixmapfunction></pixmapfunction><resources/><connections/>\n"
"</ui>";
class MyWidget : public QLabel
{
Q_OBJECT
bool m_closed = false;
public:
MyWidget(QWidget* parent = 0) : QLabel("This is MyWidget", parent) {}
bool isClosed() const { return m_closed; }
void closeEvent(QCloseEvent *) Q_DECL_OVERRIDE { m_closed = true; }
};
class MyUiLoader : public QUiLoader {
public:
MyUiLoader(QObject * parent = 0) : QUiLoader(parent) {}
QWidget * createWidget(const QString & className, QWidget * parent = 0,
const QString & name = QString()) {
if (className == "MyWidget") {
MyWidget * w = new MyWidget(parent);
w->setObjectName(name);
return w;
}
return QUiLoader::createWidget(className, parent, name);
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QBuffer buf;
buf.setData(uiData, sizeof(uiData));
MyUiLoader uiLoader;
auto uiMain = qobject_cast<MyWidget*>(uiLoader.load(&buf));
uiMain->show();
return app.exec();
}
#include "main.moc"