文章目录
- 1、使用QT_DEBUG_PLUGINS检查Qt的插件问题
- 2、QtQuick不使用OpenGL
- 3、程序在Linux上有运行无法显示
- 4、Linux打开Qt调试开关
- 5、使用QtMediaPlayer,运行时出错
- 6、Qt应用程序发布
- 7、QML中MouseArea有时无法响应触屏事件
- 8、QML中Flickable、SwipeView触摸滑动过程中插拔键盘鼠标会导致触摸失效
- 9、热拔插USB设备(如键盘鼠标)导致触屏无法响应
- 10、QML虚拟键盘按下无响应字符输出
- 11、Linux平台下QML程序无法打开FileDialog
- 12、QML应用程序设置窗口透明
- 13、Qt程序设置系统鼠标
- 14、QML Image动态刷新图片来自C++的QImage的一个巨坑
- 15、qt.qpa.plugin报xcb找到但是需要重新安装
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
(或子控件如:GridView
、ListView
等)、SwipeView
控件
进行触摸滑动过程中,如果此时进行拔插键盘鼠标,会导致滑动列表无法触摸滑动。
分析: 经过日志打印,发现正常时触摸控件有触发TouchBegin
和MouseButtonPress
事件,触摸无法滑动时抬起手指, 只触发了TouchEnd
, 未触发MouseButtonRelease
, 后续再触摸都只会触发TouchBegin
和TouchEnd
。
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
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