2014-01-28 62 views
5

當編寫一個不使用QML且不依賴於新的Qt 5特性的Qt應用程序時,我們可以用Qt 4和Qt 5編譯它(除少數源不兼容外)。與Qt 4(QtQuick 1.x)和Qt 5(QtQuick 2.x)兼容的C++/QML項目

當我們想要使用Qt 5功能,但想回到等效但效率較低的Qt 4解決方案時,我們可以簡單地使用#if來檢查Qt版本,例如,使用新的QStringLiteral,但在使用Qt 4進行編譯時回落到QString::fromUtf8

我們如何才能對QtQuick執行相同的操作?請注意,有可能在Qt 5中使用QDeclarativeViewQtQuick 1.x,但不會使用Qt 5中的新場景圖。QDeclarativeView中僅支持1.x,並且QQuickView中僅支持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但當QML文件包含QtQuick進口的聲明,我不能添加使用QGuiApplicationQQuickView#if決定1.x和2.x.是否有官方的方式,比如說,添加一個別名以使工作在QQuickView(所以它實際上被解析爲QtQuick 2.0)?

回答

3

我所做的是在部署它們時將所有QML文件中的字符串QtQuick x.y替換。如果您的源代碼樹中有一個文件夾qml,並且想要在構建樹中使用相同的qml文件夾,則可以部署文件夾,但替換字符串以匹配所需的QtQuick版本。

以下解決方案適用於POSIX系統,因爲它需要一些命令行工具;在Linux(Ubuntu)上測試。也許某個具有Windows命令行經驗的人可以爲Windows添加一個版本。

添加在您的.pro(以下代碼假設從build文件夾中,源文件夾可達與../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文件包含一個import指令,將選擇合適的QtQuick版本(你可以檢查這個你建立文件夾)。 Text元素中的字符串也被替換,因此您可以在此演示中輕鬆看到該版本。