Подтвердить что ты не робот

Qt5. Вставить объект QWidget в QML

Я использую бета Qt5 и пытаюсь встроить QWidget-объект в QML. Цель состоит в том, чтобы максимально использовать QML и использовать только объекты QWidget, где QML не делает то, что мне нужно. Я нашел ссылку, объясняющую, как это сделать для Qt4.7, но я не нашел никакой информации, объясняющей, как это сделать в Qt5.

http://doc.qt.digia.com/4.7/declarative-cppextensions-qwidgets.html

Тот же пример также доступен в папке примеров Qt5 в разделе:

Примеры\qtquick1\декларативного\cppextensions\QWidgets

К сожалению, в этом примере используется QtQuick 1, а не QtQuick 2, и я хотел бы использовать новые функции Qt5. Я действительно хочу встроить виджет qwt, но в качестве первого шага я был бы счастлив встроить любой простой объект на основе QWidget.

Может ли кто-нибудь помочь мне получить пример, работающий под Qt5/QtQuick 2?

4b9b3361

Ответ 1

Qt Quick 2 использует граф сцены для эффективного рендеринга на графическом процессоре. К сожалению, это не позволяет встроить классические виджеты в сцену. Старый подход для встраивания таких виджетов с помощью QGraphicsProxyWidget работает только с Qt Quick 1, потому что внутри него используется QGraphicsView для всех тяжеловесов, а QGraphicsProxyWidget предполагается использовать с ним.

В настоящее время нет планов по включению классических QWidgets в график сцены, о котором я знаю. Я думаю, что это вряд ли изменится, потому что концепции QPainter, рамки рисования, используемые для классических виджетов, и новый график сцены не хорошо сочетаются друг с другом.

Там предпринимаются некоторые усилия по разработке новых наборов виджетов, специально предназначенных для нужд QML, но ни один из них не обладает такими сильными и зрелыми, как классические виджеты. Наиболее известными являются QML Quick Controls, в комплекте с Qt с версии 5.1.

Если вы действительно зависите от QWT, моим советом будет придерживаться Qt Quick 1.1. Он все еще связан с Qt 5, вероятно, для таких случаев, как ваш. Таким образом, вы не сможете использовать новый график сцены.

Ответ 2

Что можно сделать, так это визуализировать виджет и загрузить его как текстуру. Для взаимодействия кому-то нужно пересылать события, такие как mouseClick или keyPressed from sceneGraph, переводить в координаты виджетов, передавать, отображать и загружать текстуру снова. Просто идея:)

Ответ 3

Рекомендуемый подход заключается в том, чтобы оставаться с приложением на основе QWidget и встраивать части QML с помощью QWidget:: createWindowContainer.

Ответ 4

Вы можете встроить QWidget в QML с помощью класса QQuickPaintedItem: http://doc.qt.io/qt-5/qquickpainteditem.html

Qt5 имеет пример: http://doc.qt.io/qt-5/qtquick-customitems-painteditem-example.html

Вы должны реализовать присущий QQuickPaintedItem атрибут частного виджета, который вы хотите внедрить. Предоставьте метод рисования, который просто отобразит QtWidget и предоставит мышь и другое событие, передающие от наследования QQuickPaintedItem, для вставки QtWidget.

Там также QSG (Qt-сценарий API), но мой опыт с этой штукой был негладким. Я считаю ключ к многопоточности (выполнение рендеринга в другом потоке (но не в Qt GUI thread one, однако в Windows это не правда, и все делается в основном потоке графического интерфейса).

Я реализовал внедрение QCustomPlot, здесь ссылка: github.com/mosolovsa/qmlplot

Ответ 5

В дополнение к ответу Жюльена - простой способ добиться этого - использовать QQuickWidget для отображения сцены QML, а затем добавить обычный QWidget в качестве дочернего элемента QQuickWidget. Вы также можете добавить простой промежуточный объект QObject для привязки QWidget к элементу в сцене.

например:.

В 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());
        }
    }
};

В main.cpp:

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();
}

В документации указывается, что использование QQuickWidget имеет преимущества перед QQuickView и QWidget:: createWindowContainer, например, никаких ограничений на порядок стекирования, но имеет "незначительный удар производительности".

Надеюсь, что это поможет.

Ответ 6

Здесь объясняется, как добавить QComboBox в макет на основе QML. Подумайте, что это хороший пример для вашего дела. (В Qt 5.9 реализован собственный контроль ComboBox QML).