加载插件是整个属性设计器的第一步要打通的功能,插件中的控件都加载不了,后面就别搞别玩下去了没法玩的,要从一个动态库中加载出来控件,肯定需要用到反射机制,以前做.NET开发的时候就觉得反射这个东西相当强大,居然可以读取DLL加载出来控件,现在用Qt,发现Qt也有反射机制,也许这东东可能各大开发语言平台都具备吧,Qt反射对应的类叫QMetaObject,着实强大,其实整个Qt开发框架也是超级强大的,本人自从转为Qt开发为主后,就深深的爱上了她,在其他跨平台的GUI开发框架平台面前,都会被Qt秒成渣,Qt的跨平台性是毋庸置疑的,几十兆的内存存储空间即可运行,尤其是嵌入式linux这种资源相当紧张的情况下,Qt的性能发挥到极致。
void frmMain::initPlugin()
{
//载入默认的插件
#if defined(Q_OS_WIN)
QString pluginName = QString("%1/quc.dll").arg(qApp->applicationDirPath());
#elif defined(Q_OS_UNIX)
QString pluginName = QString("%1/libquc.so").arg(qApp->applicationDirPath());
#elif defined(Q_OS_MAC)
QString pluginName = QString("%1/libquc.dylib").arg(qApp->applicationDirPath());
#endif
loadPlugin(pluginName);
//载入默认的控件xml数据
openFile(qApp->applicationDirPath() + "/quc.xml");
qApp->processEvents();
ui->listWidget->verticalScrollBar()->setValue(0);
}
void frmMain::loadPlugin(const QString &fileName)
{
openPlugin(fileName);
this->setWindowTitle(QString("自定义控件属性设计器(共 %1 个控件)(QQ:517216493)").arg(ui->listWidget->count()));
}
void frmMain::openPlugin(const QString &fileName)
{
qDeleteAll(listWidgets);
listWidgets.clear();
listNames.clear();
ui->listWidget->clear();
//加载自定义控件插件集合信息,包括获得类名+图标
QPluginLoader loader(fileName);
if (loader.load()) {
QObject *plugin = loader.instance();
//获取插件容器,然后逐个遍历容器找出单个插件
QDesignerCustomWidgetCollectionInterface *interfaces = qobject_cast<QDesignerCustomWidgetCollectionInterface *>(plugin);
if (interfaces) {
listWidgets = interfaces->customWidgets();
int count = listWidgets.count();
for (int i = 0; i < count; i++) {
QIcon icon = listWidgets.at(i)->icon();
QString className = listWidgets.at(i)->name();
QListWidgetItem *item = new QListWidgetItem(ui->listWidget);
item->setText(className);
item->setIcon(icon);
listNames << className;
}
}
//获取所有插件的类名
const QObjectList objList = plugin->children();
foreach (QObject *obj, objList) {
QString className = obj->metaObject()->className();
//qDebug() << className;
}
}
}