《QDebug 2022年12月》

一、Qt Widgets 问题交流

二、Qt Quick 问题交流

1、在 C++ 中关联 QQuickWindow 的 closing 信号提示 "使用了未定义类型QQuickCloseEvent"

因为 closing 信号中的参数类型是 private 模块中定义的,但是通过第二句提示我们知道找到了完整定义才能使用 Q_DECLARE_METATYPE(T*) ,而 Qt 提供了不透明指针宏 Q_DECLARE_OPAQUE_POINTER ,使得应用 Q_DECLARE_METATYPE(T*) 时不必找到完整定义。

加上此宏后即可以编译通过,只是不能接收这个参数:

Q_DECLARE_OPAQUE_POINTER(QQuickCloseEvent*)
int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [&myobj, url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
        QQuickWindow *win = qobject_cast<QQuickWindow*>(obj);
        if (win) {
            QObject::connect(win, &QQuickWindow::closing, [](){});
        }
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

另一种能够通过编译的方式是使用 SIGNAL/SLOT 宏来关联信号槽:

QObject::connect(win, SIGNAL(closing(QQuickCloseEvent*)),
                 &myobj, SLOT(onClose()));

2、QML 的文件夹对话框没有进入该目录只是单击选中那么 folder 属性获取不到这个文件夹

如图,单机选中 QtOnline 文件夹,并点击 【选择文件夹】按钮

此时打印 FolderDialog 的 folder 属性,不会出现 QtOnline ,除非双击进入这个目录

 

QtWidget 的 QFileDialog 就能正确的获取这个路径。 

测试代码:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Dialogs 1.3 as QD
import Qt.labs.platform 1.1 as Labs

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("GongJianBo")

    Button {
        text: "open"
        onClicked: {
            dialog2.open()
        }
    }

    QD.FileDialog {
        id: dialog1
        selectFolder: true
        onAccepted: {
            console.log(dialog1.folder)
        }
    }

    Labs.FolderDialog {
        id: dialog2
        onAccepted: {
            console.log(dialog2.folder)
        }
    }
}

3、BusyIndicator 如果 running 绑定 visible,那么隐藏后第二次 visible 为 true 时不会显示出来

图一是第一次 visible,图二是第二次 visible。

BusyIndicator 内部使用了一个透明度动画,runing 的时候透明度为 1,停止时为 0。而在事件处理中,透明度为 0 时又会设置 visible 为 false。

T.BusyIndicator {
    contentItem: BusyIndicatorImpl {
        running: control.running
        opacity: control.running ? 1 : 0
        Behavior on opacity { OpacityAnimator { duration: 250 } }
    }
}
void QQuickDefaultBusyIndicator::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
{
    QQuickItem::itemChange(change, data);
    switch (change) {
    case ItemOpacityHasChanged:
        if (qFuzzyIsNull(data.realValue))
            setVisible(false);
        break;
    case ItemVisibleHasChanged:
        update();
        break;
    default:
        break;
    }
}

可是即使我们调整透明度动画大于 0 ,仍然不能显示,那是因为源码用的 OpacityAnimator,只在开始和结束触发值改变的信号,而且就算指定了起止 from 和 to,最终也是在 0 和 1 变化。

不过,我们根本不需要设置 runing 为 false,因为源码中逻辑可能和我们想的不一样,我们只需要设置 visible 即可。

void QQuickDefaultBusyIndicator::setRunning(bool running)
{
    if (running)
        setVisible(true);
}

测试代码:

    Button {
        text: "pop"
        onClicked: pop.open()
    }
    Popup {
        id: pop
        contentItem: BusyIndicator {
            id: busy
            width: 80
            height: 80
            running: visible
        }
    }

三、其他

1、QImage 的数据默认至少 4 字节对齐

QImage 文档:https://doc.qt.io/qt-5.15/qimage.html

通过 bits() 返回的地址操作内部连续数据时,需要注意行对齐问题,可以通过 bytesPerLine() 获取每行字节数,也可以通过 scanLine(int i) 接口来逐行遍历。

2、QImage/QImageReader 加载修改了后缀名的图片

在旧版本中如果图片改了后缀名,QImage 可能无法正常加载,因为默认以后缀名来确认格式。可以通过 QImageReader 来读取,设置 decideFormatFromContent 为 true 后不以后缀判断格式:

    QImageReader reader(filepath);
    //setDecideFormatFromContent之前调用format会导致设置无效
    //qDebug()<<reader.format();
    reader.setDecideFormatFromContent(true);
    qDebug()<<reader.format();
    QImage img = reader.read();

在 Qt5.15 中,经测试默认可以正确加载修改了后缀的图片。 

猜你喜欢

转载自blog.csdn.net/gongjianbo1992/article/details/128509380