c++qtqmlqt5swipeview

Control Qt QML SwipeView with Signals/Slots


I'm very new to Qt, and right now struggling to figure out how to change the index of the SwipeView through a different C++ class. I'd like to make some kind of a signal that emits from the C++ class saying "Swipe Right" or something like that, and having the SwipeView respond. I'm also new to signals and slots, so I might be misunderstanding how they work.


Solution

  • When you want to control a QML element from C ++ the best strategy is to create a QObject that has Q_PROPERTY, slot and signals and export it to QML through setContextProperty(), and perform the direct binding or use Connections to connect the signals, in this case it is only necessary to emit a signal and connect it in QML.

    In the following example I show how to change to the right or left using QPushButton:

    main.cpp

    #include <QApplication>
    #include <QPushButton>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include <QHBoxLayout>
    
    class SwipeManager: public QObject{
        Q_OBJECT
    public:
        using QObject::QObject;
    public slots:
        void moveToRight(){
            emit toRight();
        }
        void moveToLeft(){
            emit toLeft();
        }
    signals:
        void toRight();
        void toLeft();
    };
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QApplication app(argc, argv);
        SwipeManager manager;
    
        QQmlApplicationEngine engine;
        engine.rootContext()->setContextProperty("manager", &manager);
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    
        QWidget w;
        QPushButton left("to left");
        QPushButton right("to right");
        QHBoxLayout *lay = new QHBoxLayout(&w);
        lay->addWidget(&left);
        lay->addWidget(&right);
        QObject::connect(&left, &QPushButton::clicked, &manager, &SwipeManager::moveToLeft);
        QObject::connect(&right, &QPushButton::clicked, &manager, &SwipeManager::moveToRight);
        w.show();
    
        return app.exec();
    }
    
    #include "main.moc"
    

    main.qml

    import QtQuick 2.9
    import QtQuick.Window 2.2
    import QtQuick.Controls 2.4
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("SwipeView Test")
    
        SwipeView {
            id: view
            anchors.fill: parent
            currentIndex: 4
            Repeater {
                model: 10
                Loader {
                    active: SwipeView.isCurrentItem || SwipeView.isNextItem || SwipeView.isPreviousItem
                    sourceComponent: Item{
                        Text {
                            text: "Page: "+index
                            anchors.centerIn: parent
                        }
                    }
                }
            }
        }
        Connections{
            target: manager
            onToRight: if(view.currentIndex + 1 != view.count) view.currentIndex += 1
            onToLeft: if(view.currentIndex != 0) view.currentIndex -= 1
        }
    
        PageIndicator {
            id: indicator
    
            count: view.count
            currentIndex: view.currentIndex
    
            anchors.bottom: view.bottom
            anchors.horizontalCenter: parent.horizontalCenter
        }
    }
    

    The complete example can be found in the following link.