Qt5. Intégrer l'objet QWidget dans QML
j'utilise Qt5 beta et j'essaie d'intégrer un objet basé sur QWidget dans QML. Le but est d'utiliser QML autant que possible, et de n'utiliser que les objets QWidget où QML ne fait pas ce dont j'ai besoin. J'ai trouvé un lien expliquant comment faire pour Qt4.7, mais je n'ai pas trouvé d'information expliquant comment faire en Qt5.
http://doc.qt.digia.com/4.7/declarative-cppextensions-qwidgets.html
sur Le même exemple est également disponible dans le dossier exemples Qt5 en vertu de l':
examplesqtquick1declarativeCPP extensionsqwidgets
malheureusement, cet exemple utilise QtQuick 1, plutôt que QtQuick 2, et j'aimerais utiliser les nouvelles fonctionnalités de Qt5. En fait, je veux intégrer un widget qwt, mais dans un premier temps, je serais heureux d'intégrer n'importe quel objet simple basé sur QWidget.
Quelqu'un peut-il m'aider à obtenir L'exemple de travail sous Qt5 / QtQuick 2 ?
6 réponses
Qt Quick 2 utilise un graphe de scène pour un rendu efficace sur le GPU. Malheureusement, cela rend impossible d'intégrer des widgets classiques dans la scène. L'ancienne approche pour incorporer ces widgets à l'aide de QGraphicsProxyWidget
ne fonctionne qu'avec Qt Quick 1, car en interne il utilise un QGraphicsView
pour tout le levage lourd et QGraphicsProxyWidget
est destiné à être utilisé avec elle.
à ce jour, il n'y a pas de plans pour permettre l'intégration des QWidgets classiques dans le graphe de scène que je connais. Je pense que c'est plutôt peu probable de changer, parce que les concepts de QPainter, le cadre de peinture utilisé pour les widgets classiques, et le nouveau graphe de scène ne joue pas bien l'un avec l'autre.
il y a quelques efforts pour développer de nouveaux ensembles de widgets spécifiquement adaptés aux besoins de QML, mais aucun d'eux n'est aussi puissant et mature que les widgets classiques. Les plus importantes sont l' QML des Contrôles Rapides, fourni avec Qt depuis la version 5.1.
si vous dépendez vraiment de QWT my le conseil serait de s'en tenir à Qt Quick 1.1 Pour l'instant. Il est toujours livré avec Qt 5, probablement pour des affaires comme la vôtre. De cette façon, vous ne prenez pas avantage de la nouvelle scène graphique.
ce qui pourrait être fait est de rendre le widget à une image et de télécharger sous forme de texture.Pour l'interaction, quelqu'un doit transmettre des événements comme mouseClick ou keyPressed à partir du sceneGraph, traduire en coordonnées widget, transmettre, rendre et télécharger la texture à nouveau. Juste une idée :)
l'approche recommandée est de rester avec une application basée sur QWidget et d'intégrer les parties QML en utilisant QWidget:: createWindowContainer.
vous pouvez intégrer QWidget à QML en utilisant la classe QQuickPaintedItem: http://doc.qt.io/qt-5/qquickpainteditem.html
Qt5 a un exemple: http://doc.qt.io/qt-5/qtquick-customitems-painteditem-example.html
vous devriez implémenter un inhérent de QQuickPaintedItem avec l'attribut widget privé, que vous voulez intégrer. Fournit la méthode paint, qui rend juste le QtWidget et fournit la souris et d'autres événements transmettant de l'héritage de QQuickPaintedItem to embed QtWidget.
il y a aussi QSG (QT scene graph API), mais mon expérience avec cette chose n'était pas facile. Je crois que l'indice dans multithreading (effectuer le rendu dans le fil différent (pas le fil Qt GUI Un, cependant sur Windows ce n'est pas vrai et tout est fait dans le fil GUI principal).
j'ai implémenté l'intégration de QCustomPlot, voici le lien: github.com/mosolovsa/qmlplot
suite à la réponse de Julien - une façon simple d'y parvenir est d'utiliser QQuickWidget pour afficher la scène QML, puis d'ajouter un QWidget régulier comme un enfant du QQuickWidget. Vous pouvez également ajouter un simple QObject intermédiaire pour ancrer le QWidget à un élément de la scène.
par exemple:
Dans le main.qml:
Item {
... // layouts, extra items, what have you
Item
{
objectName: "layoutItem"
anchors.fill: parent
}
... // more layouts, extra items, etc.
}
widgetanchor.h:
class WidgetAnchor: public QObject
{
ptr<QWidget> _pWidget;
QPointer<QQuickItem> _pQuickItem;
public:
WidgetAnchor(QWidget* pWidget, QQuickItem* pItem)
: QObject(pWidget), _pWidget(pWidget), _pQuickItem(pItem)
{
connect(_pQuickItem, &QQuickItem::xChanged, this, &WidgetAnchor::updateGeometry);
connect(_pQuickItem, &QQuickItem::yChanged, this, &WidgetAnchor::updateGeometry);
connect(_pQuickItem, &QQuickItem::widthChanged, this, &WidgetAnchor::updateGeometry);
connect(_pQuickItem, &QQuickItem::heightChanged, this, &WidgetAnchor::updateGeometry);
updateGeometry();
}
private:
void updateGeometry()
{
if (_pQuickItem)
{
QRectF r = _pQuickItem->mapRectToItem(0, QRectF(_pQuickItem->x(), _pQuickItem->y(), _pQuickItem->width(), _pQuickItem->height()));
_pWidget->setGeometry(r.toRect());
}
}
};
Dans le main.rpc:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
auto pqw = new QQuickWidget;
pqw->setSource(QUrl::fromLocalFile("main.qml"));
pqw->setResizeMode(QQuickWidget::SizeRootObjectToView);
pqw->setAttribute(Qt::WA_DeleteOnClose);
auto pOwt = new MyWidget(pqw);
if (auto pOverlayItem = pqw->rootObject()->findChild<QQuickItem*>("overlayItem"))
new WidgetAnchor(pOwt, pOverlayItem);
pqw->show();
return app.exec();
}
la documentation indique que L'utilisation de QQuickWidget a avantages par rapport à QQuickView et QWidget::createWindowContainer, comme aucune restriction sur l'ordre de cumul, mais a un "succès de performance mineur".
j'Espère que vous aide.
Ici a expliqué comment ajouter QComboBox sur la mise en page basée sur QML. Je pense que ce sera un bon exemple pour votre cas. (Dans Qt 5.9, mise en œuvre du contrôle natif de ComboBox QML).