2014-01-28 3 views
5

При написании приложения Qt, которое не использует QML и не зависит от новых функций Qt 5, мы можем скомпилировать его как с Qt 4, так и с Qt 5 (за исключением нескольких исходных несовместимостей).Проект C++/QML, совместимый с Qt 4 (QtQuick 1.x) и Qt 5 (QtQuick 2.x)

Когда мы хотим использовать функцию Qt 5, но хотим вернуться к эквивалентному, но менее эффективному решению Qt 4, мы можем просто использовать #if для проверки версии Qt, например. использовать новый QStringLiteral, но вернуться к QString::fromUtf8 при компиляции с Qt 4.

Как мы можем сделать то же самое с QtQuick? Обратите внимание, что в Qt 5 можно использовать QDeclarativeView с QtQuick 1.x, но это не будет использовать новый график сцены из Qt 5. Только 1.x поддерживается в QDeclarativeView, и только 2.x поддерживается в QQuickView, даже если я не использую введенные функции в 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; 

, а затем использовать QGuiApplication, QQuickView и так далее как в Qt 4 и Qt 5. Но когда файл QML содержит декларативный импорта для QtQuick, я не могу добавить #if, чтобы выбрать между 1.x и 2.x. Есть ли официальный способ, допустим, добавить псевдоним , чтобы сделать QtQuick 1.x работой в QQuickView (поэтому он фактически разобран как QtQuick 2.0)?

ответ

3

Что я сделал, это замена строки QtQuick x.y во всех файлах QML при их развертывании. Если у вас есть папка qml в исходном дереве и вы хотите иметь одну и ту же папку qml в дереве сборки, вы можете развернуть эту папку, но заменить строку в соответствии с нужной вами версией QtQuick.

Следующее решение работает в системах POSIX, поскольку для этого требуются некоторые средства командной строки; тестируется на Linux (Ubuntu). Возможно, кто-то, у кого есть опыт работы с командной строкой Windows, может добавить версию для Windows.

Добавить в вашем .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 

в C++ (main.cpp), вы можете создать QQuickView, который попадает обратно в QDeclarativeView для Qt 4:

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

QML файл 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 содержит директиву импорта, которая будет выбрать правильную версию QtQuick (вы можете проверить это в вашем создать папку). Строка в элементе Text также заменяется, поэтому вы легко увидите версию в этой демонстрации.

Смежные вопросы