1

I plan to create an application with QML. I have implemented a lot of qt widgets in c++. The c++ widgets should be used in QML.

How to integrate them? - path to dlls - does some qml container exist?

I didn't found good documentation for this problem

Toemmes
  • 11
  • 3
  • Possible duplicate of: http://stackoverflow.com/questions/13014415/qt5-embed-qwidget-object-in-qml or http://stackoverflow.com/questions/24735163/how-to-integrate-qwidget-in-qml-qt-quick-2-0 – derM - not here for BOT dreams Mar 27 '17 at 12:14
  • Possible duplicate of [How to integrate QWidget in QML (Qt Quick 2.0)](http://stackoverflow.com/questions/24735163/how-to-integrate-qwidget-in-qml-qt-quick-2-0) – derM - not here for BOT dreams Mar 27 '17 at 12:15
  • Maybe you should rephrase the question to indicate whether you want to use QML for building the UI component tree or if you want to use `QtQuick` as the UI component set. `QML` is ambiguous here since one can easily register `QWidget` classes with a QML engine to build a widget based UI – Kevin Krammer Mar 30 '17 at 08:35

1 Answers1

0

It's possible, but not adivisable, unless the Widgets in question have a lot of graphics (likely if you have a class based on QGraphivsView). If the widgets that you are refering to are "normal" QWidgets, please don't try to do this as it's more trouble than it's worth.

You need to create a new class that Inherit QQuickPaintedItem and override a few methods:

Header:

class QQmlWidget : public QQuickPaintedItem
{
    Q_OBJECT    
public:
    explicit QMLProfile(QWidget *internalWidget, QQuickItem *parent = 0) : QQuickPaintedItem(parent), internalWidget(internalWidget){}
    virtual ~QMLProfile();
    void paint(QPainter *painter) override;

protected:
    void mouseMoveEvent(QMouseEvent *event);
private:
    QWidget *internalWidget;
};

Cpp: (The code below is from Subsurface code, that uses QGraphivsView on QML)

void paint(QPainter* painter) {
    // let's look at the intended size of the content and scale our scene accordingly
    QRect painterRect = painter->viewport();
    QRect profileRect = internalWidget->viewport()->rect();

    qreal sceneSize = 104; // that should give us 2% margin all around (100x100 scene)
    qreal dprComp =  devicePixelRatio() * painterRect.width() / profileRect.width();
    qreal sx = painterRect.width() / sceneSize / dprComp;
    qreal sy = painterRect.height() / sceneSize / dprComp;

    // next figure out the weird magic by which we need to shift the painter so the widget is shown
    int dpr = rint(devicePixelRatio());
    qreal magicShiftFactor = (dpr == 2 ? 0.25 : (dpr == 3 ? 0.33 : 0.0));

    // now set up the transformations scale the profile and
    // shift the painter (taking its existing transformation into account)
    QTransform profileTransform = QTransform();
    profileTransform.scale(sx, sy);
    QTransform painterTransform = painter->transform();
    painterTransform.translate(-painterRect.width() * magicShiftFactor ,-painterRect.height() * magicShiftFactor);

    // apply the transformation
    painter->setTransform(painterTransform);
    internalWidget->setTransform(profileTransform);

    // finally, render the profile
    internalWidget->render(painter);
}

QQmlWidget::mouseMoveEvent(QMouseEvent *ev){
     /* Map the eveent to the Widget */
     QQuickPaintedItem(ev);
     internalWidget->mouseEvent(ev);
}

As I said, doable, but not really straigthforward. Only do that if you have no way of recreating the Widgets in QML.

Tomaz Canabrava
  • 2,320
  • 15
  • 20
  • You do not address mouse and keyboard inputs. – Benjamin T Mar 27 '17 at 12:14
  • My particular case I didn't had to address mouse input or keyboard as all I wanted was to generate a static image, For mouse and keyboard interation all you need to do is to map the events as I'v said in the code on a coment. – Tomaz Canabrava Mar 27 '17 at 12:24
  • There is a lot of mouse and keyboard input like a complete editor, tableviews with lot of business logic ... – Toemmes Mar 27 '17 at 14:29
  • If you have your custom drawing, event handling and logic separated enough from the `QWidget` container, then you can use those directly in `QQuickPaintedItem`. If your widget does not delegate but implements everything directly in its class, then a proxy approach like described in this answer might be easier than attempting separation. – Kevin Krammer Mar 30 '17 at 08:33