Připojení QML s C++ slot

0

Otázka

Vytvořil jsem aplikaci, přičemž automatické screenshoty pokaždé zdroj nakladač se mění! Snažím se připojit QML signál (screenshot()) na CPP slot (take_screenshot()). Nicméně, take_screenshot() funkce je nikdy byli povoláni i když zdroj loader je bytí změnilo a přijímám log konzole, jak dobře! Tady je moje čpp.h

 class MyClass : public QObject
 {
    Q_OBJECT
public:
MyClass(std::shared_ptr<QQmlApplicationEngine> engin)
    : m_engine(engin)
{
    QObject* root = m_engine->rootObjects()[0];
    Q_ASSERT(root != nullptr);
    QObject::connect(root, SIGNAL(screenshot()),
                     this, SLOT(take_screenshot()));
}

public slots:
int take_screenshot()
{
        QString currentDateTime = QDateTime::currentDateTime().toString( "MMMM d, yyyy, HH:mm:ss");
        QScreen *screen;
        QPixmap pixmap;
        screen = QGuiApplication::primaryScreen();
        pixmap = screen->grabWindow(0);
        QString screenshotPath = QDir::currentPath();
        QString screenShotFileName = QString("%1/%2.png").arg(screenshotPath).arg(currentDateTime);

        if (!screenShotFileName.isEmpty())
        {
            pixmap.save(screenShotFileName);
            return 1;
        }
        else
            return 0;
}

private:
std::shared_ptr<QQmlApplicationEngine> m_engine;
};

A tady je můj hlavní.qml

Window {
id: mainWindow
visible: true
width: 640
height: 480
title: qsTr("Hello World")

signal screenshot()
Loader {
         id: pageLoader
         objectName: "pageLoader"
         anchors.fill: parent
         onSourceChanged: {
         console.log("onSourceChanged_source :", pageLoader.source)
                mainWindow.screenshot()
            }
         Component.onCompleted:{
                console.log("onCompleted!", pageLoader.source)
                mainWindow.screenshot()
            }
        }
   }

Nějaké nápady o problematice, může být užitečné! Díky předem!

c++ qml qt signals-slots
2021-10-26 21:11:59
1

Nejlepší odpověď

1

Nemají přístup QML objekty v C++ jako vy, může získat neočekávané chování. V tomto případě je lepší exportovat objekt do QML, například vytvořit singleton:

utils.h

#ifndef UTILS_H
#define UTILS_H

#include <QGuiApplication>
#include <QObject>
#include <QPixmap>
#include <QQmlApplicationEngine>
#include <QScreen>
#include <QDateTime>
#include <QDir>

class Utils : public QObject
{
    Q_OBJECT
public:
    using QObject::QObject;
public slots:
    bool screenshot(){
        qDebug() << __PRETTY_FUNCTION__;
        QString currentDateTime = QDateTime::currentDateTime().toString( "MMMM d, yyyy, HH:mm:ss");
        QString screenshotPath = QDir::currentPath();
        QString filename = QString("%1/%2.png").arg(screenshotPath).arg(currentDateTime);
        if(QScreen *screen = QGuiApplication::primaryScreen()){
            QPixmap pixmap = screen->grabWindow(0);
            return pixmap.save(filename));
        }
        return false;
    }
};
#endif // UTILS_H

main.cpp

#include "utils.h"

#include <QGuiApplication>
#include <QQmlApplicationEngine>


int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

    QGuiApplication app(argc, argv);

    QScopedPointer<Utils> utils(new Utils);
    qmlRegisterSingletonInstance("Utils", 1, 0, "Utils", utils.get());

    QQmlApplicationEngine engine;

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

hlavní.qml

import QtQuick 2.15
import QtQuick.Window 2.15

import Utils 1.0

Window {
    id: mainWindow
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    Loader {
        id: pageLoader
        anchors.fill: parent
        onSourceChanged: {
            console.log("onSourceChanged_source :", pageLoader.source)
            Utils.screenshot()
        }
        Component.onCompleted:{
            console.log("onCompleted!", pageLoader.source)
            var res = Utils.screenshot()
            console.log(res)
        }
    }
}
2021-10-26 22:20:34

Je to stále volá mainWindow.screenshot(). Myslím, že jsi chtěl změnit, že Utils.screenshot(), ne?
JarMan

@JarMan ooops. díky
eyllanesc

V jiných jazycích

Tato stránka je v jiných jazycích

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................