首页 文章

C / QML项目兼容Qt 4(QtQuick 1.x)和Qt 5(QtQuick 2.x)

提问于
浏览
6

在编写不使用QML并且不依赖于新的Qt 5功能的Qt应用程序时,我们可以使用Qt 4和Qt 5编译它(除了少数源不兼容性) .

当我们想要使用Qt 5功能但希望回归到同等但效率较低的Qt 4解决方案时,我们可以简单地使用 #if 来检查Qt版本,例如:使用新的 QStringLiteral 但在使用Qt 4编译时回落到 QString::fromUtf8 .

我们怎么能用QtQuick做同样的事情?请注意,可以在Qt 5中使用 QDeclarativeViewQtQuick 1.x ,但不会使用Qt 5中的新场景图 . 在 QDeclarativeView 中仅支持 1.xQQuickView 中仅支持 2.x ,即使我不使用引入的功能在Quick 2.0中 .

我想要的是:

  • 使用Qt 4编译时,请使用 QDeclarativeView 和朋友;在QML中: import QtQuick 1.x

  • 使用Qt 5进行编译时,请使用新的 QQuickView 和朋友;在QML中: import QtQuick 2.x

  • 只有一组QML文件,但没有一个用于 QtQuick 1.x 而另一个用于 QtQuick 2.x

关于C部分,这似乎很容易 . 在Qt 4中,我们可以简单地添加:

#include <QApplication>
#include <QDeclarativeView>
#include <QDeclarativeEngine>
typedef QApplication QGuiApplication;
typedef QDeclarativeView QQuickView;

然后在Qt 4和Qt 5中使用 QGuiApplicationQQuickView 等 . 但是当QML文件包含 QtQuick 的导入声明时,我无法添加 #if 来决定1.x和2.x.有没有官方的方法,比方说,添加一个别名让 QtQuick 1.xQQuickView 中工作(所以它实际上被解析为 QtQuick 2.0 )?

1 回答

  • 3

    我所做的是在部署它们时替换所有QML文件中的字符串 QtQuick x.y . 如果源树中有一个文件夹 qml ,并且希望在构建树中具有相同的 qml 文件夹,则可以部署该文件夹,但替换该字符串以匹配所需的QtQuick版本 .

    以下解决方案适用于POSIX系统,因为它需要一些命令行工具;在Linux(Ubuntu)上测试过 . 也许具有Windows命令行经验的人可以为Windows添加版本 .

    Add in your .pro: (以下代码假定在构建文件夹中,使用 ../src/ 可以访问源文件夹;如果不是这种情况,请更改 *** 注释所在的路径)

    // Define QT5 macro for use in C++, and select the correct module for QML:
    greaterThan(QT_MAJOR_VERSION, 4) {
        DEFINES += QT5
        QT += quick
    } else {
        QT += declarative
    }
    
    // Define qmake variables for QtQuick version, and if you want, QtQuick Controls:
    equals(QT_MAJOR_VERSION, 4) {
        equals(QT_MINOR_VERSION, 7) {
            QT_QUICK_VERSION = 1.0
        }
        equals(QT_MINOR_VERSION, 8) {
            QT_QUICK_VERSION = 1.1
        }
    }
    equals(QT_MAJOR_VERSION, 5) {
        QT_QUICK_VERSION = 2.$${QT_MINOR_VERSION}
        equals(QT_MINOR_VERSION, 1): QT_QUICKCONTROLS_VERSION = 1.0
        equals(QT_MINOR_VERSION, 2): QT_QUICKCONTROLS_VERSION = 1.1
        equals(QT_MINOR_VERSION, 3): QT_QUICKCONTROLS_VERSION = 1.2
    }
    
    // Add a pre-build step which copies your qml folder
    QtQuickVersion.target = FORCE
    QtQuickVersion.commands = "rm -rf qml/;"
    QtQuickVersion.commands += "cp -r ../src/qml/ .;"  // <-- *** Here is the source path
    !isEmpty(QT_QUICK_VERSION) {
        QtQuickVersion.commands += "grep -rl 'QtQuick [0-9]\\.[0-9]' qml/ | xargs -r sed -i 's/QtQuick [0-9]\\.[0-9]/QtQuick $${QT_QUICK_VERSION}/g';"
    }
    !isEmpty(QT_QUICKCONTROLS_VERSION) {
        QtQuickVersion.commands += "grep -rl 'QtQuick.Controls [0-9]\\.[0-9]' qml/ | xargs -r sed -i 's/QtQuick.Controls [0-9]\\.[0-9]/QtQuick.Controls $${QT_QUICKCONTROLS_VERSION}/g';"
    }
    
    // Give the Makefile target *any* name which will *not* be created
    // as a file, so the step is always executed
    PRE_TARGETDEPS += FORCE
    QMAKE_EXTRA_TARGETS += QtQuickVersion
    

    In C++ (main.cpp) ,然后你可以为Qt 4创建一个 QQuickView ,它回落到 QDeclarativeView

    #ifdef QT5
    
    #include <QGuiApplication>
    #include <QQuickView>
    #include <QQmlEngine>
    
    #else
    
    #include <QApplication>
    #include <QDeclarativeView>
    #include <QDeclarativeEngine>
    typedef QApplication QGuiApplication;
    typedef QDeclarativeView QQuickView;
    // The following is the official fallback for QStringLiteral,
    // see qstring.h in Qt 5 after #ifndef QStringLiteral */
    #define QStringLiteral(str) QString::fromUtf8("" str "", sizeof(str) - 1)
    #endif
    
    
    int main(int argc, char *argv[])
    {
        QGuiApplication a(argc, argv);
    
        // (add qmlRegisterType etc.)
    
        // Open the QML view with the main QML document:
        QQuickView view;
        view.setSource(QUrl::fromLocalFile(QStringLiteral("qml/main.qml")));
        view.show();
    
        // Needed for "Qt.quit()" within QML:
        QObject::connect(view.engine(), SIGNAL(quit()), &a, SLOT(quit()));
    
        // I normally use this sizing behavior:
        view.setResizeMode(QQuickView::SizeRootObjectToView);
    
        return a.exec();
    }
    

    The QML file qml/main.qml 上面的代码打开后可以看起来像这样:

    // This import will replaced with the largest supported QtQuick version:
    import QtQuick 1.0
    
    Rectangle {
        width: 450
        height: 200
    
        Text {
            anchors.centerIn: parent
            horizontalAlignment: Text.AlignHCenter
            font.pointSize: Math.min(parent.width / 10, parent.height / 5)
    
            // This text will also be replaced to show the correct QtQuick version:
            text: "Hello from\nQtQuick 1.0!"
    
            // Some fancy animations...
            SequentialAnimation on scale {
                running: true; loops: Animation.Infinite
                NumberAnimation { from: 1; to: .6; easing.type: Easing.InOutQuad; duration: 600 }
                NumberAnimation { from: .6; to: 1; easing.type: Easing.InOutQuad; duration: 600 }
            }
            SequentialAnimation on rotation {
                running: true; loops: Animation.Infinite
                NumberAnimation { from: -10; to: 10; easing.type: Easing.InOutQuad; duration: 2000 }
                NumberAnimation { from: 10; to: -10; easing.type: Easing.InOutQuad; duration: 2000 }
            }
        }
    
        MouseArea {
            anchors.fill: parent
            onClicked: Qt.quit()
        }
    }
    

    QML文件包含一个import指令,它将选择正确的QtQuick版本(您可以在build文件夹中查看) . Text 元素中的字符串也会被替换,因此您将在此演示中轻松看到该版本 .

相关问题