Qt中QPA插件,Qt跨平台的基础

前言

Qt是一个跨平台的C++框架,各位小伙伴在使用Qt的时候有没有想过Qt是怎么实现跨平台的呢?Qt为了实现跨平台做了哪些工作。现在我们就来探讨一下Qt跨平台的基础,QPA插件。文章有点长,请各位小伙伴耐心看完。

QPA简介

QPA的全称是Qt Platform Abstraction,即Qt平台抽象层。在Qt5中替代QWS(Qt Window System)。QPA插件是通过对各种QPlatform* 类进行子类化来实现的。有几个根类,例如用于窗口系统集成的QPlatformIntegrationQPlatformWindow,以及用于更深入的平台主题和集成的QPlatformTheme。QStyle不是QPA的一部分。QPA类没有源代码或二进制兼容性保证,这意味着平台插件只能保证与它开发的Qt版本一起使用。

为什么要使用QPA

Qt一直宣称是跨平台的,但是Qt的底层却不是跨平台,在Qt底层需要调用各个系统的api完成。以QWidget为例,在Qt5中,除了qwidget.cpp还有qwidget_win.cpp、qwidget_x11.cpp、qwidget_wince.cpp等一系列各平台相关的文件。在kernel.pri中使用win32 unix:x11等包含不同的cpp文件,在编译Qt的时候,不同的平台的代码就参与编译。下面是Qt4中源码kernel.pri的一段。

win32 {
    DEFINES += QT_NO_DIRECTDRAW

    HEADERS += \
        kernel/qwinnativepangesturerecognizer_win_p.h

    SOURCES += \
        kernel/qapplication_win.cpp \
        kernel/qclipboard_win.cpp \
        kernel/qcursor_win.cpp \
        kernel/qdesktopwidget_win.cpp \
        kernel/qdnd_win.cpp \
        kernel/qmime_win.cpp \
        kernel/qsound_win.cpp \
        kernel/qwidget_win.cpp \
        kernel/qole_win.cpp \
        kernel/qkeymapper_win.cpp \
        kernel/qwinnativepangesturerecognizer_win.cpp

    !contains(DEFINES, QT_NO_DIRECTDRAW):LIBS += ddraw.lib
}

symbian {
    exists($${EPOCROOT}epoc32/include/platform/mw/akntranseffect.h): DEFINES += QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H

    SOURCES += \
        kernel/qapplication_s60.cpp \
        kernel/qeventdispatcher_s60.cpp \
        kernel/qwidget_s60.cpp \
        kernel/qcursor_s60.cpp \
        kernel/qdesktopwidget_s60.cpp \
        kernel/qkeymapper_s60.cpp\
        kernel/qclipboard_s60.cpp\
        kernel/qdnd_s60.cpp \
        kernel/qsound_s60.cpp

    HEADERS += \
        kernel/qt_s60_p.h \
        kernel/qeventdispatcher_s60_p.h

    LIBS += -lbafl -lestor

    INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE
    INCLUDEPATH += ../3rdparty/s60

    contains(QT_CONFIG, s60) {
        SOURCES += kernel/qsoftkeymanager_s60.cpp
        HEADERS += kernel/qsoftkeymanager_s60_p.h
    }
}


unix:x11 {
    INCLUDEPATH += ../3rdparty/xorg
    HEADERS += \
        kernel/qx11embed_x11.h \
        kernel/qx11info_x11.h \
        kernel/qkde_p.h

    SOURCES += \
        kernel/qapplication_x11.cpp \
        kernel/qclipboard_x11.cpp \
        kernel/qcursor_x11.cpp \
        kernel/qdnd_x11.cpp \
        kernel/qdesktopwidget_x11.cpp \
        kernel/qmotifdnd_x11.cpp \
        kernel/qsound_x11.cpp \
        kernel/qwidget_x11.cpp \
        kernel/qwidgetcreate_x11.cpp \
        kernel/qx11embed_x11.cpp \
        kernel/qx11info_x11.cpp \
        kernel/qkeymapper_x11.cpp \
        kernel/qkde.cpp

        contains(QT_CONFIG, glib) {
            SOURCES += \
        kernel/qguieventdispatcher_glib.cpp
            HEADERS += \
                kernel/qguieventdispatcher_glib_p.h
            QMAKE_CXXFLAGS += $$QT_CFLAGS_GLIB
        LIBS_PRIVATE +=$$QT_LIBS_GLIB
    }
            SOURCES += \
        kernel/qeventdispatcher_x11.cpp
            HEADERS += \
                kernel/qeventdispatcher_x11_p.h
}

虽然这样也可以实现跨平台,但是这一切都使得将Qt移植到一个新的窗口系统变的不太容易。例如我们要移植Qt到新的系统MyOS上,就需要建一系列的xxxx_myos.cpp文件。为了解决上面的问题,Qt5引入了QPA来替代,这样我们在移植Qt到MyOS上的时候就只需要新建一个MyOS的QPA插件。QPA插件在$$QTDIR/plugins/platforms下。在windows上我们可以看到qwindows.dll,在linux下有libxcb.so,他们就是QPA插件。

QPA插件的使用

我们不会直接使用QPA插件,QPA插件时Qt自己调用的,建一个简单的列子来说明

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

我们都知道QApplication是继承QGuiApplication,注意QApplication a(argc, argv),该方法直接调用QApplicationPrivate::init(),(不知道QApplicationPrivate的伙伴们可以查阅Qt-D指针和Q指针及使用)QApplicationPrivate::init()中调用
QGuiApplicationPrivate::init();在QGuiApplicationPrivate::init里面会创建QPlatformIntegration实例。QPlatformIntegration就是Qt上层与各个平台底层的桥梁,通过他或者他提供的一些接口返回的实例对象来实现平台功能。查看Qt的源码可以知道Qt先获取的QPA插件的路径platformPluginPath,该值一般为空,QPA插件的名称platformName,该值是在编译Qt的时候确定的,
QT_QPA_DEFAULT_PLATFORM_NAME在qtgui-config.h中定义,比如在windows上在qtgui-config.h会有#define QT_QPA_DEFAULT_PLATFORM_NAME "windows"

void QGuiApplicationPrivate::createPlatformIntegration()
{
    QHighDpiScaling::initHighDpiScaling();

    // Load the platform integration
    QS
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小王哥编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值