qt使用总结

1、使用QT_DEBUG_PLUGINS检查Qt的插件问题

Qt的编程中包含了插件模式,使得程序的扩展性非常好,但插件的动态加载的检查也比较严格。可以在系统的环境变量中设置export QT_DEBUG_PLUGINS=1再执行程序加载插件时,系统控制台上会输出许多加载插件时的调试信息,可以清楚的看到系统尝试加载了哪些插件,哪些是成功的,哪些没有成功,原因是什么都写的比较清楚。因此,如果自己编译的插件库无法加载,可以用这个方式检查以下到底是哪里的问题。
无法加载的原因基本有3种 :

  • 编译的插件库没有放在正确的目录下,程序根本没找到。
  • 插件库运行需要其他库的支持(比如数据库驱动插件,需要额外的相关数据库连接库),如果系统没有找到这些相关库,虽然可以找到你的插件,同样会无法加载。
  • Build Key不兼容的问题,也就是说主程序编译的环境和插件编译的环境不兼容,导致插件和主程序可能无法调用,因此Qt也无法加载这些插件。

2、QtQuick不使用OpenGL

方法:在入口函数调用QQuickWindow::setSceneGraphBackend(QSGRendererInterface::Software);
链接

3、程序在Linux上有运行无法显示

分析: 可能由于环境变量设置了QT_QPA_PLATFORM=linuxfb
方法: 删除程序运行时环境的该变量设置。

4、Linux打开Qt调试开关

方法export QT_DEBUG_PLUGINS=1

5、使用QtMediaPlayer,运行时出错

问题:控制台打印

defaultServiceProvider::requestService(): no service found for - "org.qt-project.qt.mediaplayer"

方法

  • Windows:把qt安装目录下的plugins下的mediaservice文件夹整个拷到运行目录下。
  • Linux:

6、Qt应用程序发布

(1)Windows平台使用Qt自带windeployqt拷贝依赖项

在Windows平台下,Qt自带程序windeployqt.exe。路径一般在bin目录下,例如:C:\Program Files\qt-5.12.0-windows-x64-msvc\bin
方法
控制台进入到windeployqt.exe所在目录。输入:windeployqt.exe 指定exe程序文件,例如:

windeployqt.exe D:\workspace\test\build\Release\test.exe

如果打包的是QML应用程序,则需要指定选项-qmldir 工程中qml文件所在目录,例如:

windeployqt.exe -qmldir D:\workspace\test\src\view D:\workspace\test\build\Release\test.exe

则会把Qt相关依赖项拷贝到exe程序文件所在目录。
在这里插入图片描述

(2)Linux平台使用linuxdeployqt发布

在Linux平台下,需要到https://github.com/probonopd/linuxdeployqt下载源码并编译出linuxdeployqt程序。
方法:
打开终端,输入:linuxdeployqt 可执行程序文件 -appimage,例如:

linuxdeployqt qt_test -appimage

如果打包的是QML应用程序,则需要指定选项-qmldir 工程中qml文件所在目录,例如:

linuxdeployqt qt_test -appimage -qmldir=/media/jaron/test/src/view

则会把Qt相关依赖项拷贝到程序文件所在目录。
在这里插入图片描述

7、QML中MouseArea有时无法响应触屏事件

Linux环境下,在QML中利用MouseArea实现按钮控件,控件有时候会无法响应触屏事件,但是应用程序有收到相关事件。
分析: MouseArea对触摸事件的支持不好,更多是用于鼠标事件。
方案: 使用MultiPointTouchArea进行触摸事件的监听,如果不想支持鼠标事件,则把其mouseEnabled属性设置为false

8、QML中Flickable、SwipeView触摸滑动过程中插拔键盘鼠标会导致触摸失效

Linux环境下,在QML中对Flickable(或子控件如:GridViewListView等)、SwipeView控件
进行触摸滑动过程中,如果此时进行拔插键盘鼠标,会导致滑动列表无法触摸滑动。
分析: 经过日志打印,发现正常时触摸控件有触发TouchBeginMouseButtonPress事件,触摸无法滑动时抬起手指, 只触发了TouchEnd, 未触发MouseButtonRelease, 后续再触摸都只会触发TouchBeginTouchEnd

class MyApplication : public QGuiApplication
{
public:
    MyApplication(int& argc, char** argv) : QGuiApplication(argc, argv) {}
    virtual ~MyApplication() = default;
    
    bool notify(QObject* object, QEvent* event) override
    {
        switch (event->type())
        {
        case QEvent::MouseButtonPress:
            printf("mouse press at %s\n", object->objectName().toStdString().c_str());
            break;
        case QEvent::MouseButtonRelease:
            printf("mouse release at %s\n", object->objectName().toStdString().c_str());
            break;
        case QEvent::KeyPress:
            printf("keyboard press at %s\n", object->objectName().toStdString().c_str());
            break;
        case QEvent::KeyRelease:
            printf("keyboard release at %s\n", object->objectName().toStdString().c_str());
            break;
        case QEvent::TouchBegin:
            printf("touch begin at %s\n", object->objectName().toStdString().c_str());
            break;
        case QEvent::TouchUpdate:
            printf("touch update at %s\n", object->objectName().toStdString().c_str());
            break;
        case QEvent::TouchEnd:
            printf("touch end at %s\n", object->objectName().toStdString().c_str());
            break;
        }
        return QGuiApplication::notify(object, event);
    }
};

方案: 触发滑动列表的触摸事件时,同时发送鼠标事件。

class MyApplication : public QGuiApplication
{
public:
    MyApplication(int& argc, char** argv) : QGuiApplication(argc, argv) {}
    virtual ~MyApplication() = default;

    bool notify(QObject* object, QEvent* event) override
    {
        bool handled = false;
        switch (event->type())
        {
        case QEvent::MouseButtonPress: { 
            printf("mouse press at %s\n", object->objectName().toStdString().c_str());
        } 
        break;
        case QEvent::MouseButtonRelease: { 
            printf("mouse release at %s\n", object->objectName().toStdString().c_str());
        }
        break;
        case QEvent::KeyPress: {
            printf("keyboard press at %s\n", object->objectName().toStdString().c_str());
        }
        break;
        case QEvent::KeyRelease: {
            printf("keyboard release at %s\n", object->objectName().toStdString().c_str());
        }
        break;
        case QEvent::TouchBegin: {
            printf("touch begin at %s\n", object->objectName().toStdString().c_str());
            auto quickItem = qobject_cast<QQuickItem*>(object);
            if (quickItem)
            {
                std::string typeName(quickItem->metaObject()->className());
                if ("QQuickFlickable" == typeName || "QQuickListView" == typeName || "QQuickGridView" == typeName || "QQuickTableView" == typeName)
                {
                    m_slideableObject = object;
                    auto touchEvent = static_cast<QTouchEvent*>(event);
                    const auto& point = touchEvent->touchPoints().first();
                    QMouseEvent mouseEvent(QEvent::MouseButtonPress, point.pos().toPoint(), point.screenPos().toPoint(), Qt::LeftButton, Qt::LeftButton, touchEvent->modifiers());
                    QGuiApplication::sendEvent(object, &mouseEvent);
                    handled = true;
                }
            }
            break;
        }
        case QEvent::TouchUpdate: {
            printf("touch update at %s\n", object->objectName().toStdString().c_str());
            if (m_slideableObject && m_slideableObject == object)
            {
                auto touchEvent = static_cast<QTouchEvent*>(event);
                const auto& point = touchEvent->touchPoints().first();
                QMouseEvent mouseEvent(QEvent::MouseMove, point.pos().toPoint(), point.screenPos().toPoint(), Qt::LeftButton, Qt::LeftButton, touchEvent->modifiers());
                QGuiApplication::sendEvent(object, &mouseEvent);
                handled = true;
            }
        }
        break;
        case QEvent::TouchEnd: {
            printf("touch end at %s\n", object->objectName().toStdString().c_str());
            if (m_slideableObject && m_slideableObject == object)
            {
                auto touchEvent = static_cast<QTouchEvent*>(event);
                const auto& point = touchEvent->touchPoints().first();
                QMouseEvent mouseEvent(QEvent::MouseButtonRelease, point.pos().toPoint(), point.screenPos().toPoint(), Qt::LeftButton, Qt::LeftButton, touchEvent->modifiers());
                QGuiApplication::sendEvent(object, &mouseEvent);
                handled = true;
            }
        }
        break;
        }
        if (handled)
        {
            return false;
        }
        return QGuiApplication::notify(object, event);
    }

private:
    QObject* m_slideableObject = nullptr;
};

同时,如果QML中滑动列表的项是可点击控件的话,那么滑动列表需要禁用交互interactive,然后由项控件监听触摸事件去控制滑动列表的滑动。

9、热拔插USB设备(如键盘鼠标)导致触屏无法响应

最近在Linux上开发基于Qt5.7.0应用程序,设备支持触摸屏(USB接口),发下了一个问题:当拔出键盘或鼠标时,同时快速点击程序界面上的可点击控件,会有较大概率出现界面触摸不在响应事件到控件上,此时杀死应用程序再次启动就又可以响应触摸事件。
分析: 可能由于USB设备的热拔插,导致其他USB设备会暂时断开又连接上,但是Qt5.7.0库对于热拔插支持不好,导致触摸屏断开又重新连接上后,应用程序无法再次自动识别到触摸屏设备,而重启应用程序后,应用程序在启动时会先把所有USB设备都加载一遍。
方案: 修改Qt5.7.0库的设备检测源码,然后重新编译Qt库。源码模块为:qt-everywhere-src-5.7.0\qtbase\src\platformsupport\devicediscovery,需要修改文件:
qdevicediscovery_static_p.h

/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#ifndef QDEVICEDISCOVERY_STATIC_H
#define QDEVICEDISCOVERY_STATIC_H

//
//  W A R N I N G
//  -------------
//
// This file is not part of the Qt API.  It exists purely as an
// implementation detail.  This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//

#include "qdevicediscovery_p.h"
#include <QFileSystemWatcher>
#include <QStringList>

QT_BEGIN_NAMESPACE

class QDeviceDiscoveryStatic : public QDeviceDiscovery
{
    Q_OBJECT

public:
    QDeviceDiscoveryStatic(QDeviceTypes types, QObject *parent = 0);
    QStringList scanConnectedDevices() override;

private:
    bool checkDeviceType(const QString &device);
    
private slots:
    /**
     * @brief 处理文件监听事件
     * @param path 变化的文件(这里时热拔插的设备文件)
     */
    void handleHotPlugWatch(const QString &path);
    
private:
    QFileSystemWatcher *m_fileWatcher; /* 文件监听器, 用于检测热插拔 */
    QStringList m_devices; /* 原有的设备列表 */
};

QT_END_NAMESPACE

#endif // QDEVICEDISCOVERY_STATIC_H

qdevicediscovery_static.cpp

/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qdevicediscovery_static_p.h"

#include <QStringList>
#include <QCoreApplication>
#include <QObject>
#include <QHash>
#include <QDir>
#include <QLoggingCategory>
#include <QtCore/private/qcore_unix_p.h>

#ifdef Q_OS_FREEBSD
#include <dev/evdev/input.h>
#else
#include <linux/input.h>
#endif
#include <fcntl.h>

/* android (and perhaps some other linux-derived stuff) don't define everything
 * in linux/input.h, so we'll need to do that ourselves.
 */
#ifndef KEY_CNT
#define KEY_CNT                 (KEY_MAX+1)
#endif
#ifndef REL_CNT
#define REL_CNT                 (REL_MAX+1)
#endif
#ifndef ABS_CNT
#define ABS_CNT                 (ABS_MAX+1)
#endif
#ifndef ABS_MT_POSITION_X
#define ABS_MT_POSITION_X       0x35
#endif
#ifndef ABS_MT_POSITION_Y
#define ABS_MT_POSITION_Y       0x36
#endif

#define LONG_BITS (sizeof(long) * 8 )
#define LONG_FIELD_SIZE(bits) ((bits / LONG_BITS) + 1)

static bool testBit(long bit, const long *field)
{
    return (field[bit / LONG_BITS] >> bit % LONG_BITS) & 1;
}

QT_BEGIN_NAMESPACE

Q_LOGGING_CATEGORY(lcDD, "qt.qpa.input")

QDeviceDiscovery *QDeviceDiscovery::create(QDeviceTypes types, QObject *parent)
{
    return new QDeviceDiscoveryStatic(types, parent);
}

QDeviceDiscoveryStatic::QDeviceDiscoveryStatic(QDeviceTypes types, QObject *parent)
    : QDeviceDiscovery(types, parent)
{
    /* 初始化文件监听器 */
    m_fileWatcher = new QFileSystemWatcher(this);
    m_fileWatcher->addPath(QString::fromLatin1(QT_EVDEV_DEVICE_PATH)); /* 添加监听路径: dev/input/ */
    connect(m_fileWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(handleHotPlugWatch(QString)));
    qCDebug(lcDD) << "static device discovery for type" << types;
}

QStringList QDeviceDiscoveryStatic::scanConnectedDevices()
{
    QStringList devices;
    QDir dir;
    dir.setFilter(QDir::System);

    // check for input devices
    if (m_types & Device_InputMask) {
        dir.setPath(QString::fromLatin1(QT_EVDEV_DEVICE_PATH));
        const auto deviceFiles = dir.entryList();
        for (const QString &deviceFile : deviceFiles) {
            QString absoluteFilePath = dir.absolutePath() + QLatin1Char('/') + deviceFile;
            if (checkDeviceType(absoluteFilePath))
                devices << absoluteFilePath;
        }
    }

    // check for drm devices
    if (m_types & Device_VideoMask) {
        dir.setPath(QString::fromLatin1(QT_DRM_DEVICE_PATH));
        const auto deviceFiles = dir.entryList();
        for (const QString &deviceFile : deviceFiles) {
            QString absoluteFilePath = dir.absolutePath() + QLatin1Char('/') + deviceFile;
            if (checkDeviceType(absoluteFilePath))
                devices << absoluteFilePath;
        }
    }

    qCDebug(lcDD) << "Found matching devices" << devices;

    return devices;
}

bool QDeviceDiscoveryStatic::checkDeviceType(const QString &device)
{
    int fd = QT_OPEN(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
    if (Q_UNLIKELY(fd == -1)) {
        qWarning() << "Device discovery cannot open device" << device;
        return false;
    }

    qCDebug(lcDD) << "doing static device discovery for " << device;

    if ((m_types & Device_DRM) && device.contains(QLatin1String(QT_DRM_DEVICE_PREFIX))) {
        QT_CLOSE(fd);
        return true;
    }

    long bitsAbs[LONG_FIELD_SIZE(ABS_CNT)];
    long bitsKey[LONG_FIELD_SIZE(KEY_CNT)];
    long bitsRel[LONG_FIELD_SIZE(REL_CNT)];
    memset(bitsAbs, 0, sizeof(bitsAbs));
    memset(bitsKey, 0, sizeof(bitsKey));
    memset(bitsRel, 0, sizeof(bitsRel));

    ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(bitsAbs)), bitsAbs);
    ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(bitsKey)), bitsKey);
    ioctl(fd, EVIOCGBIT(EV_REL, sizeof(bitsRel)), bitsRel);

    QT_CLOSE(fd);

    if ((m_types & Device_Keyboard)) {
        if (testBit(KEY_Q, bitsKey)) {
            qCDebug(lcDD) << "Found keyboard at" << device;
            return true;
        }
    }

    if ((m_types & Device_Mouse)) {
        if (testBit(REL_X, bitsRel) && testBit(REL_Y, bitsRel) && testBit(BTN_MOUSE, bitsKey)) {
            qCDebug(lcDD) << "Found mouse at" << device;
            return true;
        }
    }

    if ((m_types & (Device_Touchpad | Device_Touchscreen))) {
        if (testBit(ABS_X, bitsAbs) && testBit(ABS_Y, bitsAbs)) {
            if ((m_types & Device_Touchpad) && testBit(BTN_TOOL_FINGER, bitsKey)) {
                qCDebug(lcDD) << "Found touchpad at" << device;
                return true;
            } else if ((m_types & Device_Touchscreen) && testBit(BTN_TOUCH, bitsKey)) {
                qCDebug(lcDD) << "Found touchscreen at" << device;
                return true;
            } else if ((m_types & Device_Tablet) && (testBit(BTN_STYLUS, bitsKey) || testBit(BTN_TOOL_PEN, bitsKey))) {
                qCDebug(lcDD) << "Found tablet at" << device;
                return true;
            }
        } else if (testBit(ABS_MT_POSITION_X, bitsAbs) &&
                   testBit(ABS_MT_POSITION_Y, bitsAbs)) {
            qCDebug(lcDD) << "Found new-style touchscreen at" << device;
            return true;
        }
    }

    if ((m_types & Device_Joystick)) {
        if (testBit(BTN_A, bitsKey) || testBit(BTN_TRIGGER, bitsKey) || testBit(ABS_RX, bitsAbs)) {
            qCDebug(lcDD) << "Found joystick/gamepad at" << device;
            return true;
        }
    }

    return false;
}

void QDeviceDiscoveryStatic::handleHotPlugWatch(const QString &path)
{
    if (path.compare(QString::fromLatin1(QT_EVDEV_DEVICE_PATH)))
    {
        return;
    }
    /* 先移除原来的设备 */
    foreach (const QString &device, m_devices)
    {
        emit deviceRemoved(device);
    }
    /* 获取现在的设备, 注: 这里获取的设备已经经过过滤, 原因是在对该类进行实例化的时候, 已经传进了筛选参数, 如: QDeviceDiscovery::Device_Keyboard */
    m_devices = scanConnectedDevices();
    /* 重新添加设备 */
    foreach (const QString &device, m_devices)
    {
        emit deviceDetected(device);
    }
}

QT_END_NAMESPACE

链接:让Qt5的USB触摸屏/键盘/鼠标支持热插拔

10、QML虚拟键盘按下无响应字符输出

现象: 在Linux系统中使用QML开发界面应用程序,程序启动后虚拟键盘按下按下无响应(在输入框中没有按下的字符显示),QML文件的加载方式如下:

QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
Window {
    id: window
    flags: Qt.FramelessWindowHint
    width: 1024
    height: 600
    minimumWidth: width
    minimumHeight: height
    maximumWidth: width
    maximumHeight: height
    Component.onCompleted: {
        window.show()
    }
}

分析: 可能QQmlApplicationEngine在加载QML时,没有初始化输入法。
解决: 通过创建QQuickView进行QML文件加载,方式如下:

QQuickView view;
view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
view.setFlag(Qt::Window);
view.setFlag(Qt::FramelessWindowHint);
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.resize(QSize(1024, 600));
view.showFullScreen();
Item {
    width: 1024
    height: 600
}

11、Linux平台下QML程序无法打开FileDialog

现象: 开发了QML应用程序,使用了FileDialog组件,在Windows平台下可以打开,移植到Linux平台下打开时出现错误:

ERROR: No native FileDialog implementation available.
Qt Labs Platform requires Qt Widgets on this setup.
Add 'QT += widgets' to .pro and create QApplication in main().

解决: 应用程序的工程文件(如:CMakeLists.txt)需要加上Qt::Widgets库的使用,
在这里插入图片描述
同时,应用程序不能使用QGuiApplication,需要使用QApplication替换。
在这里插入图片描述

12、QML应用程序设置窗口透明

在QML应用程序中,对边框进行圆角或者半透明或者阴影处理。
方法一
可以先利用Canvas把整个窗口设置为全透明,再进行其他效果的渲染。例如:

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls.Styles 1.4

Window {
    readonly property int GAP: 10 /* 间隙 */

    id: window
    width: 1024 + GAP
    height: 600 + GAP
    flags: Qt.Window | Qt.FramelessWindowHint
    visible: true

    /* 设置窗口全透明 */
    Canvas {
        anchors.fill: parent
        function render() {
            var ctx = getContext("2d")
            ctx.clearRect(0, 0, width, height)
            ctx.fillStyle = Qt.rgba(0, 0, 0, 0) /* 重点: 第4个参数值范围[0, 1], 设置为0表示整个窗口全透明 */
            ctx.fillRect(0, 0, width, height)
            requestAnimationFrame(render)
        }
        Component.onCompleted: {
            requestAnimationFrame(render)
        }
    }

    /* 黑色圆角半透明 */
    Rectangle {
        anchors.fill: parent
        color: "#000000"
        opacity: 0.03
        radius: 3
    }
    
    /* 其他界面元素根节点 */
    Item {
        anchors.centerIn: parent
        width: parent.width - GAP
        height: parent.height - GAP
        
        // TODO: 添加其他界面元素
    }
}

方法二

QSurfaceFormat surfaceFormat;
surfaceFormat.setAlphaBufferSize(8); /* 设置透明通道位数 */
QQuickView view;
view.setFlag(Qt::FramelessWindowHint);
view.setFormat(surfaceFormat);
view.setClearBeforeRendering(true);
view.setColor(QColor(Qt::transparent)); /* 设置背景透明 */

QML中设置颜色为透明
Rectangle {
	color: "#00000000" /* "transparent" */
	Image {
		anchors.fill: parent
		source: "qrc:/image/res/login_wdg.png" /* 图片是带圆角的透明图片 */
	}
}

13、Qt程序设置系统鼠标

  • 设置鼠标不显示,可以通过设置空白鼠标实现:QGuiApplication::setOverrideCursor(QCursor(Qt::BlankCursor));
  • 恢复鼠标:QGuiApplication::restoreOverrideCursor();

14、QML Image动态刷新图片来自C++的QImage的一个巨坑

https://blog.csdn.net/qq_43248127/article/details/89599824

15、qt.qpa.plugin报xcb找到但是需要重新安装

现象: 运行qt程序时出现错误

QFactoryLoader::QFactoryLoader() checking directory path "/kds/bin/platforms" ...
loaded library "/opt/qt-5.15.10-kylin-arm64/plugins/platforms/libqxcb.so"
qt.qpa.xcb: could not connect to display
qt.qpa.xcb: could not connect to display
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "/opt/qt-5.15.10-kylin-arm64/plugins/platforms" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: eglfs (from /opt/qt-5.15.10-kylin-arm64/plugins/platforms), linuxfb (from /opt/qt-5.15.10-kylin-arm64/plugins/platforms), minimal (from /opt/qt-5.15.10-kylin-arm64/plugins/platforms), minimalegl (from /opt/qt-5.15.10-kylin-arm64/plugins/platforms), offscreen (from /opt/qt-5.15.10-kylin-arm64/plugins/platforms), vnc (from /opt/qt-5.15.10-kylin-arm64/plugins/platforms), wayland-egl (from /opt/qt-5.15.10-kylin-arm64/plugins/platforms), wayland (from /opt/qt-5.15.10-kylin-arm64/plugins/platforms), wayland-xcomposite-egl (from /opt/qt-5.15.10-kylin-arm64/plugins/platforms), wayland-xcomposite-glx (from /opt/qt-5.15.10-kylin-arm64/plugins/platforms), webgl (from /opt/qt-5.15.10-kylin-arm64/plugins/platforms), xcb (from /opt/qt-5.15.10-kylin-arm64/plugins/platforms), eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, wayland-egl, wayland, wayland-xcomposite-egl, wayland-xcomposite-glx, webgl, xcb.

此种现象需要先确认linux是否有桌面系统(例如:ukui、gnome等)。

(1)有桌面系统

方法: 查看依赖库libqxcb.so是否缺少其他依赖

ldd /kds/lib/qt-5.12.0-ubuntu-x64-/plugins/platforms/libqxcb.so

提示

libxcb-xinerama.so.0 => not found

重新安装libxcb-xinerama0

apt install --reinstall libxcb-xinerama0

(2)无桌面系统

无桌面系统的环境是不支持xcb,Qt窗口的渲染需要改为使用linux framebuffer,需要设置环境变量:

export QT_QPA_PLATFORM=linuxfb
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值