57650


こんにちは、Kaedeです。  
以前、質問した「[qmlのui上にwidgetで作成したuiを取り込む方法](https://ja.stackoverflow.com/questions/57194/qml%E3%81%AEui%E4%B8%8A%E3%81%ABwidget%E3%81%A7%E4%BD%9C%E6%88%90%E3%81%97%E3%81%9Fui%E3%82%92%E5%8F%96%E3%82%8A%E8%BE%BC%E3%82%80%E6%96%B9%E6%B3%95)」の回答をもとに、`Widget(ui)`を`QML拡張プラグイン`として登録し、別プロジェクトの`SwipeView`に配置してみました。

しかし、ビルドは通るものの、実行をすると以下ダイアログが表示された後「再試行」でクラッシュしてしまいます。

[![エラーダイアログ](https://i.stack.imgur.com/oUeZk.png)](https://i.stack.imgur.com/oUeZk.png)

エラーメッセージは以下の通りです。(一部..に置き換えています。)

[code]

    Starting C:\..\Qt_Project\swipeTestPrj\swipeTestPrj\..build\debug\swipeTestPrj.exe...
    QML debugging is enabled. Only use this in a safe environment.
    ASSERT: "!d->isWidget" in file kernel\qobject.cpp, line 1979
    プログラムが突然終了しました。
    The process was ended forcefully.
    C:/../Qt_Project/swipeTestPrj/swipeTestPrj/..build/debug/swipeTestPrj.exe crashed.
    
[/code]

【環境】  
・Qt Creator 4.5.1 (Community)  
・Qt 5.10.1  
・Qt Quick 2.9  
・windows 10 Pro , MSVC++ Compiler 15.8

このエラーを解決する方法について、ご存知の方がいればご教授頂きたいです。

* * *

[19/08/21追記]  
以下ファイル構成とソースコードです。

**ファイル構成**  
[![ファイル構成](https://i.stack.imgur.com/v00F3.png)](https://i.stack.imgur.com/v00F3.png)

**swipeTestPrj.pro**

[code]

    include(../QmlInWidgetElement/qmlinwidgetelement.pri) #追記
    
    QT += quick widgets
    CONFIG += c++11
    DEFINES += QT_DEPRECATED_WARNINGS
    SOURCES += main.cpp
    RESOURCES += qml.qrc
    
    # Default rules for deployment.
    qnx: target.path = /tmp/$${TARGET}/bin
    else: unix:!android: target.path = /opt/$${TARGET}/bin
    !isEmpty(target.path): INSTALLS += target
    
    
[/code]

**qmlinwidgetelement.pri**

[code]

    QT += quick widgets
    INCLUDEPATH += $$PWD
    
    # Input
    SOURCES += $$PWD/mywidgetitem.cpp
    HEADERS += $$PWD/mywidgetitem.h
    FORMS += $$PWD/mywidgetitem.ui
    DISTFILES += $$PWD/qmldir
    
[/code]

**mywidgetitem.h**

[code]

    #ifndef MYWIDGETITEM_H
    #define MYWIDGETITEM_H
    
    #include <QWidget>
    
    namespace Ui {
    class MyWidgetItem;
    }
    
    class MyWidgetItem : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit MyWidgetItem(QWidget *parent = nullptr);
        ~MyWidgetItem();
    
    private:
        Ui::MyWidgetItem *ui;
    };
    
    #endif // MYWIDGETITEM_H
    
    
[/code]

**mywidgetitem.cpp**

[code]

    #include "mywidgetitem.h"
    #include "ui_mywidgetitem.h"
    
    MyWidgetItem::MyWidgetItem(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::MyWidgetItem)
    {
        ui->setupUi(this);
    }
    
    MyWidgetItem::~MyWidgetItem()
    {
        delete ui;
    }
    
    
[/code]

**main.cpp**

[code]

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    // Add
    #include <mywidgetitem.h>
    #include <QApplication>
    #include <QQuickView>
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QApplication app(argc, argv);
    
        // Add-
        qmlRegisterType<MyWidgetItem>("WidgetElements", 1, 0, "MyWidgetItem");
        // ----
    
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
        if (engine.rootObjects().isEmpty())
            return -1;
    
    
        return app.exec();
    }
    
    
[/code]

**main.qml**

[code]

    import QtQuick 2.10
    import QtQuick.Controls 2.3
    import WidgetElements 1.0 // Add
    
    ApplicationWindow {
        visible: true
        width: 640
        height: 480
        title: qsTr("Tabs")
    
        SwipeView {
            id: swipeView
            anchors.fill: parent
    
            Page1Form {
            }
    
            Page2Form {
            }
            // Add-
            MyWidgetItem{
                /* ここにWidgetを使って作成した画面を表示したい */
            }
            // ----
        }
    
    }
    
    
[/code]

**mywidgetitem.h**  
・Buttonをいくつか適当に配置する

**~ui.qml**  
・Labelをいくつか適当に配置する


CC BY-SA 4.0
2019-08-20T01:18:36.720
57467
2019-08-28T03:31:56.370
2019-08-21T07:04:22.540
35314
35314
question
c++ qt qt5 qt-creator
QtのQML拡張プラグイン使用でアプリがクラッシュしてしまう


`ASSERT`
というのは、「ある関数を正しくない使い方したこと」を呼ばれた側の関数が自己チェックして指摘したというものです。元ソース見てませんのでアレですが

`kernel\qobject.cpp` の 1979 行を含んでいる関数をあなたのプログラムが呼ぶとき、仮引数としてポインタ引数 `d`
があるわけですが、この構造体 / クラスのメンバ `isWidget` は `0` (または空ポインタ) でなければならないのに、非 `0`
値が入っているので使い方が間違っているからプログラムごと終了させちゃうよ

というのが `ASSERT` の意味合いです。

似たような質疑応答  
<https://forum.qt.io/topic/23090/how-to-create-a-window-using-qml>  
によると Qt のバージョン違いによって仕様が変わっているところなので書き直しが必要、みたいなことが書いてあります。


CC BY-SA 4.0
2019-08-21T04:00:47.540
57501
2019-08-21T04:00:47.540
8589
57467
answer


QMLの中にQWidgetを埋め込みたいということですよね?

残念ながらスマートな方法はなさそうです。  
QtQuick2ではGPUでの効率的なレンダリングを実現するために、旧来のC++コードでのレンダリングは簡単には埋め込めないようです。

参考URL  
<https://stackoverflow.com/questions/13014415/qt5-embed-qwidget-object-in-qml>

この質問では  
* QtQuick1を使い、QGraphicsProxyWidgetを経由して表示する  
* QQuickPaintedItemを使ってウィジェットをレンダリングし、イベントも仲介する。  
といった解決が提示されてますね。

ちなみにアサートについては、「QWidgetは親としてQWidgetしか受け取れない」ところをそれ以外のクラスを受け取ったために発生してると思います。(setParentが仮想関数じゃないせいでちょっとわかりづらくなってる)


CC BY-SA 4.0
2019-08-28T03:31:56.370
57650
2019-08-28T03:31:56.370
35629
57467
answer