從Qt4.x 遷移到Qt5問題彙總

如果想把Qt4.x上面開發的軟件在Qt5上面正常運行,如果什麼都不做的話估計會出現各做各樣的錯誤,筆者也是經歷過這種迷茫痛,後面才發現官方已有系統發文一一提及到諸多遷移會遇到的問題以及解決辦法。附上官網地址,以供參考http://qt-project.org/wiki/Transition_from_Qt_4.x_to_Qt5

爲了提高開發者的開發效率,我對這個文檔大致做一個翻譯,也算爲大家提供中文版的解決方案吧,如有異議,請參考原文。

1. QtWidgets 是一個獨立的模塊

例如,編譯出現如下錯誤

    error: QMainWindow: No such file or directory

    error: QToolButton: No such file or directory

    error: QWidget: No such file or directory

解決方法:

在工程的 *.pro文件中添加下面內容:

    QT += widgets

同時把頭文件

    #include <QtGui>

更改爲

    #include <QtWidgets>

這樣代碼就可以正常運行了,不過有時候需要添加更詳細的頭文件,例如

    #include <QtWidgets/QtoolButton>

2.QtWebKitWidgets也是一個獨立的模塊

例如,編譯的時候出現如下錯誤:

    error: invalid use of incomplete type 'class QWebFrame'

    error: forward declaration of 'class QWebFrame'

解決方法:

在工程的 *.pro 文件中添加:

    QT += webkitwidgets

備註:當已經有QT += webkitwidgets ,就不需要添加 QT += widgets

同時把工程文件裏面添加的所有

    #include <QtWebKit>

更改爲

    #include <QtWebKitWidgets>

3.QPrinter 不起作用

如果你已經添加了如下兩行

    #include <QPrinter>

    #include <QPrintDialog>

在工程的 *.pro 文件中添加:

    QT += printsupport

如果還是不能工作,把添加的

    #include <QPrinter>

    #include <QprintDialog>

更改爲

    #include <QtPrintSupport/QPrinter>

    #include <QtPrintSupport/QPrintDialog>

4.沒有toAscii() 和 fromAscii()方法

    fromAscii()

    toAscii()

替換成

    fromLatin1()

    toLatin1()

例如,在 Qt 4 上的代碼

    QByteArray configfileti = TMP_Config.toAscii();

更改成

    QByteArray configfileti = TMP_Config.toLatin1();

5.去掉了QCoreApplication::UnicodeUTF8 

因爲Qt5都是採用 UnicodeUTF8的編碼方式,所以 UnicodeUTF8這個枚舉類型就顯得有點多此一舉了,所以刪掉了所有的關於QCoreApplication::UnicodeUTF8參數的傳遞。

例如:

    Href_Gui->setWindowTitle(QApplication::translate("Href_Gui", "Url / www", 0, QApplication::UnicodeUTF8));

    label->setText(QApplication::translate("Href_Gui", "Text:", 0, QApplication::UnicodeUTF8));

    label_2->setText(QApplication::translate("Href_Gui", "Url:", 0, QApplication::UnicodeUTF8));

    label_3->setText(QApplication::translate("Href_Gui", "Target / Name:", 0, QApplication::UnicodeUTF8));

更改爲:

    Href_Gui->setWindowTitle(QApplication::translate("Href_Gui", "Url / www", 0));

    label->setText(QApplication::translate("Href_Gui", "Text:", 0));

    label_2->setText(QApplication::translate("Href_Gui", "Url:", 0));

    label_3->setText(QApplication::translate("Href_Gui", "Target / Name:", 0));

6.去掉了QWorkspace類

在Qt4.3中,這個類就已經被 QMdiArea類替換掉了,在Qt5中把QWorkspace類正式刪除掉了。QMdiArea類和QWorkspace類有類似的API接口,只是需要更改下一些方法,信號和槽的接口名字即可。

替換

    #include <QWorkspace>

    #include <QMdiArea>

7.QDrag類問題

應用的拖拽功能或許需要一些微調,例如

    QDrag *drag = new QDrag(event->widget());

在 Qt 5 會有如下錯誤

    error: no matching function for call to 'QDrag::QDrag(QWidget*)'

加上如下頭文件或許可以解決如上錯誤

    #include <QWidget>

8.刪掉了qFindChildren

如果遇到如下錯誤

    error: 'qFindChildren' was not declared in this scope

解決辦法

用findChildren 方法替代qFindChildren ,需要注意的是,調用方法的方式略有改變。參考如下例子:

    toString(const QObject* obj, int indentLevel) const {

    [...]

        /* Query over QObjects */

        if (m_children) {

            QList<QObject*> childlist = qFindChildren<QObject*>(obj, QString());

    [...]

把上述例子中的如下代碼

    QList<QObject*> childlist = qFindChildren<QObject*>(obj, QString());

替換成如下代碼

    QList<QObject*> childlist = obj->findChildren<QObject*>(QString());

9.刪掉了qVariantValue 

編譯時報如下錯誤

    error: 'qVariantValue' was not declared in this scope

這個函數等同於QVariant::value<T>(value)。因此可以把如下代碼

    QTime t = qVariantValue<QTime>(val);

更改爲

    QTime t = val.value<QTime>();

This QTime enclosed in the angled brackets lets the compiler know what QVariant will return. However, if the variable is not a QVariable the type enclosed in the angled brackets should not be used(doing so will result in a vague compile time error). So given that m_color is of type QColor you will rewrite

    s.setValue("color/favorite", qVariantValue<QColor>(m_color));

to

    s.setValue("color/favorite", m_color.value());

10.刪除了qVariantCanConvert

替換

    Q_ASSERT(qVariantCanConvert<QString>(variant));

    Q_ASSERT(qVariantCanConvert<QSize>(variant));

    Q_ASSERT(qVariantCanConvert<QFont>(fontVariant));

    Q_ASSERT(variant.canConvert(QMetaType::QString));

    Q_ASSERT(variant.canConvert(QMetaType::QSize));

    Q_ASSERT(fontVariant.canConvert(QMetaType::QFont));

11.刪掉了Qt::escape 

    error: 'escape' is not a member of 'Qt'

So you would change the following block:

        if (result == QString())

            result = Qt::escape(val.toString());

        else

            result = Qt::escape(result);

        return result;

to

        if (result == QString())

            result = QString(val.toString()).toHtmlEscaped();

        else

            result = QString(result).toHtmlEscaped();

        return result;

12.刪掉了QDesktopServices::storageLocation 

    error: 'storageLocation' is not a member of 'QDesktopServices'

    error: 'DataLocation' is not a member of 'QDesktopServices'

用 QStandardPaths::StandardLocation代替,把如下

    QString path = s.value("db.path", QDesktopServices::storageLocation(QDesktopServices::DataLocation)).toString();

替換爲

    QString path = s.value("db.path", QStandardPaths::standardLocations(QStandardPaths::DataLocation)).toString();

13.刪掉了CONFIG+=qtestlib 

If you have the above line in your project file the compiler will warn you in the compile window, nonetheless the code will still run as usual:

如果在工程文件中有上面這一行,編譯器將在編譯窗口中產生警告:

    Project WARNING: CONFIG+=qtestlib is deprecated. Use QT+=testlib instead.

14.QWeakPointer quirks

A code block like

    quint64 decodedPointer = line.toULongLong();

    MetaData* md = reinterpret_cast<MetaData*>(decodedPointer);

    QWeakPointer<MetaData> wp(md);

results in

    error: no matching function for call to 'QWeakPointer<MetaData>::QWeakPointer(MetaData*&)'

To fix this add to the project file:

    DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0

15.QtConcurrent Library is Missing?

    C:\Qt\Qt5.0.2\5.0.2\mingw47_32\include\QtConcurrent\qtconcurrentthreadengine.h:133: error: undefined reference to `_imp___ZN12QtConcurrent16ThreadEngineBaseD2Ev'

In Qt 4, QtConcurrent was part of QtCore, so there was no need to include specific headers. This is no longer the case with Qt 5. If your source code have lines like

    m_current = QtConcurrent::blockingMappedReduced(slices, functor, stitchReduce, QtConcurrent::UnorderedReduce );

You will need to include the header:

    #include <QtConcurrent/QtConcurrent>

and add the following line to your project file:

    LIBS += -lQt5Concurrent

16.Fixing #include<> Headers

A Perl script “fixqt4headers.pl” exists in qtbase/bin/. that should be run on source code using Qt that corrects the #include<> directives for Qt components to also consider the module name.

17.Plugin loading

The Q_EXPORT_PLUGIN,Q_EXPORT_PLUGIN2 macros have been deprecated in favor of the new Q_PLUGIN_METADATA macro. The advantage of the new system is that it allows Qt to query the metadata for the plugin without actually dlopen’ing it. This greatly improves performance and reliability of the plugin system.

The new Q_PLUGIN_METADATA macro is included next to the Q_OBJECT macro in the QObject derived class that is returned when loading the plugin. It contains the plugins IID and a filename pointing to a json file containing the metadata for the plugin. The json file is compiled into the plugin and does not need to be installed.

An example on how to change your plugins can be found by looking at the patch that changes the Gif image format plugin, see http://qt.gitorious.org/qt/qtbase/commit/963b4c1647299fd023ddbe7c4a25ac404e303c5d .

18.Deploying to systems without C++11

When Qt is built from source code on a system with C++11 installed, the Qt libraries/frameworks are linked against the system’s C++11 library (libc++). This means that the Qt libraries/frameworks are not deployable to systems without C++11 installed (such as out-of-the-box Mac OS X 10.6). To be able to deploy to systems that only support the older C++ standard (libstdc++), build Qt from source code with the -no-c++11 configure option.

19.QTimer is no longer accurate to the millisecond by default

QTimer has now 3 accuracy types, with a new default behaviour:

    The new default type is Qt::CoarseTimer which, to reduce power/CPU consumption, allow 5% difference between requested time and actual one, and even allow the timer to fire before the requested time.

    The former one is Qt::PreciseTimer (to the millisecond, never before the requested time).

    A third one is Qt::VeryCoarseTimer and allow a 1 second difference

20.QUrl addQueryItem moved to QUrlQuery

If you have:

    QUrl url;

    // ...

    url.addQueryItem(key, value);

You will want to change it to

    QUrl url;

    QUrlQuery urlQuery;

    // ...

    urlQuery.addQueryItem(key, value);

     

    url.setUrlQuery(urlQuery);

21.QAbstractItemModel changes

    void reset()

    void setRoleNames(const QHash<int, QByteArray> & roleNames)

both have changed and are now protected.

See Compatibility Members for QAbstractItemModel [qt-project.org]

Recommended Reading

    C++ API Changes [qt-project.org]

    The porting guide [qt-project.org]

    Porting Desktop Applications from Qt 4 to Qt 5 [blog.ics.com]

    Porting from Qt 4 to Qt 5 [kdab.com]

    Automated porting from Qt 4 to Qt 5 [kdab.com]

Categories:

    Developing_Qt

    Developing_with_Qt

                             


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章