2301_81469198 2024-09-11 11:42 采纳率: 50%
浏览 45
已结题

Qt Quick Android 项目报错及显示问题

优先采纳真人回答!

这是一个Qt Quick(安卓)应用程序,使用QML和C++开发,部署到真机后出现了多个显示问题及报错,希望大家可以帮我解决!

理想效果:

(1) 侧边栏打开前

img

(2) 侧边栏打开后

img

代码:

main.qml


import QtQuick
import QtQuick.Controls
import QtQuick.Layouts


Window {

    function pt(_pt) {
        var ppi = Qt.application.primaryScreen.pixelDensity * 25.4;
        const scaleFactor = 2;
        return _pt * (ppi / 72) * scaleFactor;
    }

    visible: true
    visibility: Window.FullScreen

    Rectangle {
        id: drawer
        width: parent.width * 0.7
        height: parent.height
        z: 2

        property bool isOpened: !touchArea.isMoving && x === 0

        Component.onCompleted: {
            x = -width
        }

        gradient: Gradient {
            GradientStop { position: 0.0; color: "#CCFFE6" }
            GradientStop { position: 1.0; color: "#FFCCCC" }
        }

        NumberAnimation {
            id: drawerOpen
            target: drawer
            property: "x"
            to: 0
            duration: Math.abs(drawer.x / parent.width * 0.2)
              // 根据初始位置计算动画时长
        }

        NumberAnimation {
            id: drawerClose
            target: drawer
            property: "x"
            to: -width
            duration: Math.abs(drawer.x / parent.width * 0.2)
        }
    }

    MultiPointTouchArea {
        id: touchArea
        anchors.fill: parent
        maximumTouchPoints: 1  // 限制为单点触控

        property real startX: 0  // 记录手势开始的X坐标
        property real lastX: 0   // 记录手势结束的X坐标
        property bool isMoving: false

        onIsMovingChanged: {
            drawerOpen.stop()
            drawerClose.stop()
        }

        // 捕捉手势开始
        onPressed: {
            startX = touchPoints[0].x
            lastX = drawer.x
            isMoving = true
        }

        // 捕捉手势移动
        onUpdated: {
            if (touchPoints.length > 0) {
                var delta = touchPoints[0].x - startX  // 手指移动的距离
                var newPosition = lastX + delta  // 根据手指滑动更新Drawer位置

                // 确保Drawer的位置在合理的范围内
                drawer.x = Math.max(-drawer.width, Math.min(newPosition, 0));
            }
        }

        // 捕捉手指松开,决定是否展开或隐藏
        onReleased: {
            if (drawer.x > -drawer.width / 2) {
                drawerOpen.start();  // 如果超过一半,则展开Drawer
            } else {
                drawerClose.start();  // 如果不到一半,则隐藏Drawer
            }
            isMoving = false
        }
    }

    Rectangle {
        id: mainPage
        anchors.fill: parent
        x: drawer.x + drawer.width

        Button {
            z: 1
            anchors.fill: parent
            opacity: 0.4 * (-drawer.x / drawer.width)
            visible: drawer.isOpened || touchArea.isMoving
            onClicked: {
                if (!touchArea.isMoving)
                    drawerClose.start()
            }
        }

        z: 0

        Rectangle {
            id: header
            anchors.top: parent.top
            width: parent.width
            height: pt(120)
            color: "#3399FF"

            Component.onCompleted: {
                statusBarHandler.setStatusBarColor("#3399FF")
            }

            Button {
                id: opendrawer
                anchors.left: parent.left
                anchors.margins: pt(40)
                height: pt(120)
                width: pt(120)
                background: Rectangle {
                    anchors.fill: parent
                    color: "#3399FF"
                    radius: pt(60)
                }

                onClicked: {
                    if (!touchArea.isMoving)
                        drawerOpen.start()
                }
            }

            TextField {
                anchors.fill: parent
                horizontalAlignment: Text.AlignHCenter
                verticalAlignment: Text.AlignVCenter
                placeholderText: "搜索组织"
                placeholderTextColor: "lightgray"
                font.pixelSize: pt(20)
                anchors.centerIn: parent

                background: Rectangle {
                    id: searchingBox
                    color: "white"
                    anchors.centerIn: parent
                    border.color: "transparent"
                    width: pt(520)
                    height: pt(100)
                    radius: pt(50)
                    border.width: 0
                }
            }

            Rectangle {
                id: gradientColorBox
                anchors.top: header.bottom
                anchors.horizontalCenter: header.horizontalCenter
                width: header.width
                height: header.height

                gradient: Gradient {
                    GradientStop {
                        position: 0.0
                        color: "#3399FF"
                    }
                    GradientStop {
                        position: 1.0
                        color: "#00000000"
                    }
                }
            }
            Rectangle {
                color: "#D4D4D4"
                anchors.horizontalCenter: header.horizontalCenter
                anchors.top: gradientColorBox.bottom

                GridLayout {
                    id: gridLayout
                    anchors.fill: parent
                    columns: Math.floor(Screen.width - pt(120)) / pt(580)
                    anchors.leftMargin: pt(80)
                    anchors.rightMargin: pt(80)
                    rowSpacing: pt(40)  // 行间距
                    columnSpacing: pt(40)  // 列间距

                    Component {
                        id:infocard

                        Rectangle {
                            color: "white"
                            width: pt(540)
                            height: pt(520)
                            radius: pt(40)
                        }
                    }

                    function addItem() {
                        var newItem = infocard.createObject(gridLayout);  // 创建新对象
                        if (newItem) {
                            gridLayout.addItem(newItem);  // 添加到 GridLayout 中
                        }
                    }

                    Component.onCompleted: {
                        for (var i = 0; i < 5; i++)
                            addItem()
                    }
                }
            }
        }
    }
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#include "app_environment.h"
#include "import_qml_components_plugins.h"
#include "import_qml_plugins.h"

#include <QJniObject>
#include <QCoreApplication>

class StatusBarHandler : public QObject {
    Q_OBJECT
public:
    explicit StatusBarHandler(QObject *parent = nullptr) : QObject(parent) {}

    Q_INVOKABLE void setStatusBarColor(const QString &colorHex) {
    #ifdef Q_OS_ANDROID
        // 通过 QJniObject 获取当前 Android 的 Activity
        QJniObject activity = QJniObject::callStaticObjectMethod(
            "org/qtproject/qt5/android/QtNative",  // Qt 在 Android 上提供的类
            "activity",
            "()Landroid/app/Activity;");  // 返回类型是 Activity

        if (activity.isValid()) {
            QJniObject window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;");
            if (window.isValid()) {
                // 解析颜色
                jint colorInt = QJniObject::callStaticMethod<jint>(
                    "android/graphics/Color",
                    "parseColor",
                    "(Ljava/lang/String;)I",
                    QJniObject::fromString(colorHex).object<jstring>()
                    );

                // 设置状态栏颜色
                window.callMethod<void>("setStatusBarColor", "(I)V", colorInt);
            }
        }
    #endif
    }
};

int main(int argc, char *argv[])
{
    set_qt_environment();

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    const QUrl url(u"qrc:/qt/qml/Main/main.qml"_qs);
    QObject::connect(
        &engine,
        &QQmlApplicationEngine::objectCreated,
        &app,
        [url](QObject *obj, const QUrl &objUrl) {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
        },
        Qt::QueuedConnection);

    // 将 StatusBarHandler 类注册为 QML 中的对象
    StatusBarHandler statusBarHandler;
    engine.rootContext()->setContextProperty("statusBarHandler", &statusBarHandler);

    engine.addImportPath(QCoreApplication::applicationDirPath() + "/qml");
    engine.addImportPath(":/");

    engine.load(url);

    if (engine.rootObjects().isEmpty()) {
        return -1;
    }

    return app.exec();
}

#include "main.moc"

而实际效果是:

(开发环境:Windows11 x64、Qt6.6.2开源版、Qt Creator 12.0.2)
(构建套件:Android Qt 6.6.2 Clang arm64-v8a JDK17 NDK25 SDK16 android-35 Android12.0+13.0)
(运行环境:华为Mate 20 HMA-AL00 Harmony4.0.0(Qt识别为:Android 10.0) 屏幕2244*1080)

1、setStatusBarColor(color) 调用后,设备上的状态栏仍是黑色的
2、除了侧边栏 drawer 在程序开始运行时可以显示0.5秒左右,其他的组件均不显示,屏幕一片空白
3、在主页面 mainPage 用手指向右滑动,侧边栏 drawer 不显示

报错信息:

1、W libAppApp_arm64-v8a.so: qrc:/qt/qml/Main/main.qml:117:13: TypeError: Cannot read property 'pixelDensity' of undefined
2、W libAppApp_arm64-v8a.so: qrc:/qt/qml/Main/main.qml:129:17: TypeError: Cannot read property 'pixelDensity' of undefined
3、W libAppApp_arm64-v8a.so: qrc:/qt/qml/Main/main.qml:128:17: TypeError: Cannot read property 'pixelDensity' of undefined
4、W libAppApp_arm64-v8a.so: qrc:/qt/qml/Main/main.qml:157:21: TypeError: Cannot read property 'pixelDensity' of undefined
5、W libAppApp_arm64-v8a.so: qrc:/qt/qml/Main/main.qml:156:21: TypeError: Cannot read property 'pixelDensity' of undefined
6、W libAppApp_arm64-v8a.so: qrc:/qt/qml/Main/main.qml:200:29: TypeError: Cannot read property 'pixelDensity' of undefined
7、W libAppApp_arm64-v8a.so: qrc:/qt/qml/Main/main.qml:201:29: TypeError: Cannot read property 'pixelDensity' of undefined
8、W libAppApp_arm64-v8a.so: qrc:/qt/qml/Main/main.qml:200:29: RangeError: Maximum call stack size exceeded.
9、W libAppApp_arm64-v8a.so: qrc:/qt/qml/Main/main.qml:201:29: RangeError: Maximum call stack size exceeded.

注:第117 128 129 156 157 200 201行:

img


img


img

_10、W libAppApp_arm64-v8a.so: qrc:/qt/qml/Main/main.qml:39: ReferenceError: parent is not defined
11、W libAppApp_arm64-v8a.so: qrc:/qt/qml/Main/main.qml:48: ReferenceError: parent is not defined
_

注:第39、48行:

img

12、W libAppApp_arm64-v8a.so: qrc:/qt/qml/Main/main.qml:68: TypeError: Cannot read property 'x' of undefined
注:第68行:

img

希望大家可以帮我解决以上报错和显示问题,谢谢!
最好可以使程序达到开头的理想效果

  • 写回答

24条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2024-09-11 11:43
    关注
    获得0.40元问题酬金

    以下回复引自免费微信小程序:皆我百晓生。 如问题解决,还请采纳。如仍有疑问,请回复留言或私信博主,以便获得更精准的帮助。

    在ANDROID的QT QUICK项目中遇到的问题及解决方案:

    问题1:侧边栏打开前出现错误

    问题描述:当用户侧边栏打开时,QT QUICK应用崩溃并打印出以下错误信息:

    EXCEPTION IN THREAD "MAIN" (SIGSEGV):
    SEGV: SEGMENTATION FAULT (0X40000000)
    

    解决方案:

    1. 检查QT文件夹中的BUILD/QML目录及其子目录是否正确安装。
    2. 确保QML/SRC/APP/路径下包含了QMLQML/SRC/MAIN/RESOURCES/等文件。
    3. 调整QT配置文件中的--NO-COMPILE参数或--DISABLE-QML选项以忽略QT QUICK的编译过程。

    问题2:侧边栏打开后出现错误

    问题描述:当用户侧边栏打开后,QT QUICK应用崩溃并打印出以下错误信息:

    EXCEPTION IN THREAD "MAIN" (SIGSEGV):
    SEGV: SEGMENTATION FAULT (0X40000000)
    

    解决方案:

    1. 在QT配置文件中修改--ENABLE-QML参数为--ENABLE-DEBUG,这样可以允许QT进行调试。
    2. 检查QML/SRC/MAIN/RESOURCES/目录下的QML文件是否存在。
    3. 确保QML/SRC/APP/路径下包含了QMLQML/SRC/MAIN/RESOURCES/等文件,并且它们是可用的。

    总结:

    • 需检查QT文件夹中的正确安装,确保QMLQML/SRC目录下有相应文件。
    • 根据错误信息调整QT配置文件中的相关参数。
    • 检查QML/SRC/MAIN/RESOURCES/目录下QML文件的可用性。

    以上就是在ANDROID的QT QUICK项目中遇到的一些常见问题及解决方案,希望对您有所帮助。

    评论

报告相同问题?

问题事件

  • 系统已结题 9月19日
  • 修改了问题 9月11日
  • 修改了问题 9月11日
  • 创建了问题 9月11日