[Solved] Cannot access custom widgets loaded by uiloader
-
i've created a designer plugin with custom widgets. I can use them in the Designer.
During run-time i want to load these widgets. But even though i can see my widgets in the created gui, i cant get access to them programmatically...
@
QUiLoader loader;
loader.addPluginPath("."); //copied the designer lib to the path
qDebug() << loader.availableWidgets(); //recognizes custom widgetsQWidget* gui = loader.load(new QFile("form.ui")); //FlipButton is a customWidget derived from QToolButton QList<FlipButton*> flips = gui->findChildren<FlipButton*>(); qDebug() << flips.size(); // prints zero qDebug() << flips;
@
Loading standard qt widgets, works fine.
Printing them via
@
qDebug() << gui->findChildren<QWidget*>();
@
Shows ... FlipButton(0x8a8aa80, name = "flipButton") ...
in the output, which suggests that the right custom class is created in memory.But how can i access them?
Any help is greatly appreciated. -
found a workaround.
@
QList<QWidget*> list = gui->findChildren<QWidget*>();
foreach(QWidget* w, list)
{
customWidget* cw;
if((cw=static_cast<customWidget*>(w)))
//...
}
@alternatively use dynamic_cast or reinterpret_cast works
aswell. Weird that qobject_cast always fails tho.
Shrug -
Hi,
If qobject_cast fails then there's something fishy going on. Can you provide a minimal compilable sample application that reproduce this behavior ?
Also, which OS/Qt version are you running ?
-
Im using Ubuntu 13.10 with Qt5.2.0 (32bit).
I omitted the files mywidgetplugin.{h,cpp} mywidget.{h,cpp} for brevity. They were automatically created by wizard (new project->other project->qt custom designer widget)designer project file
@
CONFIG += plugin release
TARGET = mywidgetplugin
TEMPLATE = libHEADERS = mywidgetplugin.h mywidget.h
SOURCES = mywidgetplugin.cpp mywidget.cpp
LIBS += -L.QT += designer
target.path = /path/to/plugins/designer
client.path = /path/to/client/
client.files = libmywidgetplugin.soINSTALLS += target client
@client project file
@
QT = core gui uitools widgets
TARGET = untitled
TEMPLATE = appINCLUDEPATH += /path/to/designerPluginProject
VPATH += /path/to/designerPluginProject
HEADERS += mywidget.h
SOURCES += main.cpp
@
client main.cpp
@
#include <QApplication>
#include <QDebug>
#include <QUiLoader>
#include <QFile>
#include <QWidget>
#include "mywidget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QUiLoader loader;
loader.clearPluginPaths();
loader.addPluginPath(".");
if( !loader.availableWidgets().contains("myWidget") )
qDebug() << "UiLoader did not read custom widgets library";QWidget* gui = loader.load(new QFile("form.ui")); gui->show(); myWidget* mw = gui->findChild<myWidget*>(); qDebug() << "Found a myWidget? " << (mw!=NULL); QList<myWidget*> mws = gui->findChildren<myWidget*>(); qDebug() << "Found myWidgets? " << !mws.isEmpty(); QWidget* qwidget = gui->findChild<QWidget*>(); qDebug() << "Found qwidget? " << (qwidget!=NULL); qDebug() << "dynamic_cast to myWidget?" << (dynamic_cast<myWidget*>(qwidget)!=NULL); qDebug() << "qobject_cast to myWidget?" << (qobject_cast<myWidget*>(qwidget)!=NULL); qDebug() << "list childs : " << gui->findChildren<QWidget*>(); return a.exec();
}
@form.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>402</width>
<height>302</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="myWidget" name="myWidget"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>myWidget</class>
<extends>QWidget</extends>
<header>mywidget.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@When running client it prints:
@
main-Found a myWidget? false
main-Found myWidgets? false
main-Found qwidget? true
main-dynamic_cast to myWidget? true
main-qobject_cast to myWidget? false
main-list childs : (myWidget(0x863f438, name = "myWidget") )
@Im also not sure why i need to add VPath in client.pro
Thanks for helping :) -
Got it! Wasnt linking against the plugin. Thought Qt would do it automatically...
client project file
@
//...
INCLUDEPATH += /path/to/designerPluginProject
LIBS += -L. -lmywidgetplugin
@When running client it prints:
@
main-Found a myWidget? true
main-Found myWidgets? true
main-Found qwidget? true
main-dynamic_cast to myWidget? true
main-qobject_cast to myWidget? true
main-list childs : (myWidget(0x94200f8, name = "myWidget") )
@ -
IIRC you should have two libraries, one containing your widget and the other that is the current designer plugin. So you link your project to the library and not the plugin and you can update the library without the need to recompile the plugin (unless e.g. you are adding new widgets)
-
Let my try rephrase for understanding:
create designer plugin containing custom widgets
create shared/static library which also contains the widgets
link project against the second
The advantage of this approach:
I can change the implementation (.cpp) of my custom widgets in the second library as long as the interface (.h or public stuff + properties) does not change with having to touch the designer lib.
Object if wrong! -
I object ! But you almost got it
Here is the right order:
Create library containing the widgets
Create designer plugin linking to that lib
Link project to the first
So you have only one lib containing the widgets