Обработчик сигнала QML не отвечает на сигнал C ++ - PullRequest
0 голосов
/ 31 октября 2019

У меня есть простая программа, которая включает передачу сигналов между QML и C ++.

В настоящее время у меня есть два случая, когда мне нужно передать сигнал с C ++ на QML.

Первый - из одного из моих исходных файлов / классов, «Поиск», а второй - из другогоc ++ исходный файл / класс "Node".

Сигналы в первом случае принимаются динамически созданным объектом QML с использованием parent.dynamic_object_name = Qt.createQmlObject(QString,parent,'name');

. В этом динамическом объекте следующий код получает сигнал "someAction"

import Search 1.0

...

Search {
    id: search
}
Connections {
    target: search
    onSomeAction: {
        dosomething()
    }
}

И это сработало для меня. Поиск регистрируется через qmlregistertype. И dosomething () успешно вызывается.

Однако во втором случае, хотя я убедился, что формат точно такой же, он не работает.

Во втором случае я получаю сигнал от "Node.cpp". Я следовал той же процедуре, регистрируя «Узел» с помощью qmlRegisterType. На этот раз я пытаюсь получить сигнал в main.qml.

import Node 1.0

...

Node {
    id: node
}
Connections {
    target: node
    onCreateNode: {
        newNode()
    }
}

Не выдается сообщение об ошибке. Показывая, что программа знает, что мой сигнал существует, он просто не реагирует на него. Я просмотрел онлайн и увидел, что не может быть более одного обработчика сигналов, в противном случае активен только последний. Таким образом, я попытался удалить свой обработчик сигнала в моем динамическом объекте, однако я все еще не могу получить сигнал. Таким образом, это не проблема.

Я рассмотрел возможность того, что мой эмиттер использует экземпляр "Node", отличный от того, который я зарегистрировал. Это действительно было так, но после исправления проблема осталась.

Здесь приведены соответствующие фрагменты:

Класс узла:

class Node: public QObject
{
    Q_OBJECT
public:
    Node(QObject * parent = nullptr);
    Q_INVOKABLE void getNode(int id);
    Q_INVOKABLE void acceptedSelection(QString selection, int x, int y);
    void generateNode(int id);
    int xPos;
    int yPos;

private:
    struct nodeInfo{
        int x;
        int y;
        QString text;
        int width;
        int height;
        int fontSize;
        int color;
        int parent;
        QVector<int> children;

    };
    QVector<nodeInfo> nodeMap;

signals:
    void createNode(QString nodeData);
public slots:
};

Сигнал, отправленный с узла. Программа успешно выдает «сгенерировать по имени».

void Node::generateNode(int id)
{
    QString xpos = QString::number(nodeMap[id].x);
    QString ypos = QString::number(nodeMap[id].y);
    QString width = QString::number(nodeMap[id].width);
    QString height = QString::number(nodeMap[id].width);
    QString nodeData = QString("import QtQuick 2.0; Rectangle{x:%1;y:%2;width:%3;height:%4}").arg(
                xpos,ypos,width,height);
    qDebug()<<"generate called";
    emit createNode(nodeData);
}

main.qml:


ApplicationWindow {
    id:mywin
    objectName: "AppWindow"
    visible: true
    width: 1600
    height: 900
    title: qsTr("Qmap")

    Node {
        id: mynode;
    }

    Item{
        id: myitem
        anchors.fill: parent
        focus:true
        Connections {
            id: nodeconnect;
            target: mynode;
            onCreateNode:{
                console.log("hi");
            }
        }

Чтобы уточнить, я не понимаю, почему в одной и той же программе с той же реализацией одинсигнал работает, а другой нет. Если я пропустил любую необходимую информацию, пожалуйста, сообщите мне. Любая помощь приветствуется.

Полный код: main.qml

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick 2.0
import QtQuick 2.6
import QtQuick.Controls 2.0
import QtQuick.Controls 1.4

import Node 1.0
import Search 1.0

ApplicationWindow {
    id:mywin
    objectName: "AppWindow"
    visible: true
    width: 1600
    height: 900
    title: qsTr("Qmap")
    menuBar: MenuBar{

        Menu {
            title: "File"
            MenuItem{text: "open"}
        }
        Menu {
            title: "Edit"
            MenuItem{text:"undo"}
        }
    }
    Node {
        id: mynode;
    }

    Item{
        id: myitem
        anchors.fill: parent
        focus:true



        property int mouse_lastx: 0;
        property int mouse_lasty: 0;

        MouseArea{
            id: mousearea
            hoverEnabled: true
            anchors.fill: parent
            onPositionChanged: {
                myitem.mouse_lastx = mouseX
                myitem.mouse_lasty = mouseY
            }
        }

        Connections {
            id: nodeconnect;
            target: mynode;
            onCreateNode:{
                console.log("hi");
            }
        }



        Keys.onTabPressed: {

            create_rect(mouse_lastx,mouse_lasty)

        }

        property string find:"
        import QtQuick 2.0;
        import Search 1.0
        import Node 1.0
        FocusScope{
            id: scope;
            focus:true;
            x:%1;
            y:%2;

            Rectangle {
                id: suggestionBox;
                color: 'grey';
                border.width:2;
                width:200;
                height:135;
                x:-5000
                y:34
                Text {
                    id: first;
                    x: 5;
                    y: 5;
                    text: '';
                }
                Text {
                    id: second;
                    x: 5;
                    y: 30;
                    text: '';
                }
                Text {
                    id: third;
                    x: 5;
                    y: 55;
                    text: '';
                }
                Text {
                    id: fourth;
                    x: 5;
                    y: 80;
                    text: '';
                }
                Text {
                    id: fith;
                    x: 5;
                    y: 105;
                    text: '';
                }
                Rectangle {
                    id: selectionBox;
                    color:'#33000000';
                    border.width:2;
                    width: 200;
                    height:25;
                    x: 0;
                    y: 0;
                }
            }

            Rectangle {
                id:newrect;
                color: 'grey';
                border.width: 4;
                width: 200;
                height: 30;
                focus:true;

                x:0;
                y:0;
                Node {
                    id: node;
                }
                Search {
                    id: search;
                }
                Connections {
                    id: searchconnect
                    target: search;
                    onBoxHide: {
                        suggestionBox.x = -10000;
                    }
                    onBoxUpdated: {
                        suggestionBox.height = (5-empty)*27;
                        suggestionBox.x = 0;
                        first.text = search.getSuggestions(0)
                        second.text = search.getSuggestions(1)
                        third.text = search.getSuggestions(2)
                        fourth.text = search.getSuggestions(3)
                        fith.text = search.getSuggestions(4)

                    }
                    onSpacebarPressed: {
                        selectionBox.y = selectionBox.y + 25;
                    }
                    onCycleSelection: {
                        selectionBox.y = 0;
                    }
                }
                property int xbuffer: %3;
                property int ybuffer: %4;

                TextInput {
                    id: input;
                    focus: true;
                    x:5;

                    y:5;

                    onTextChanged: {
                        search.searchBox(input.text)

                    }

                    onAccepted: {

                        node.acceptedSelection(search.getSuggestions(search.getSelection()),newrect.xbuffer,newrect.ybuffer);
                        scope.x = -400;
                        scope.y = -100;

                    }

                }
                Component.onCompleted:{
                    input.forceActiveFocus();
                }

            }
        }"




        property var dynamic_object: Qt.createQmlObject((find.arg(-300).arg(-100)).arg(-300).arg(-100),myitem,'rect')
        function create_rect(x,y){
            var xloc = x;
            var yloc = y;
            myitem.dynamic_object.destroy(0);
            myitem.dynamic_object = Qt.createQmlObject((find.arg(xloc).arg(yloc).arg(xloc).arg(yloc)),myitem,'rect');
            myitem.dynamic_object.forceActiveFocus();


        }


        }
}

node.h, за которым следует node.cpp

//node.h
#ifndef NODE_H
#define NODE_H

#include <QObject>
#include <QVector>
#include <QDebug>
#include <string>
using namespace std;

class Node: public QObject
{
    Q_OBJECT
public:
    Node(QObject * parent = nullptr);
    Q_INVOKABLE void getNode(int id);
    Q_INVOKABLE void acceptedSelection(QString selection, int x, int y);
    void generateNode(int id);
    int xPos;
    int yPos;

private:
    struct nodeInfo{
        int x;
        int y;
        QString text;
        int width;
        int height;
        int fontSize;
        int color;
        int parent;
        QVector<int> children;

    };
    QVector<nodeInfo> nodeMap;

signals:
    void createNode(QString nodeData);
public slots:
};

#endif // NODE_H

//node.cpp
#include "node.h"
using namespace std;

Node::Node(QObject * parent):
    QObject (parent)
{

}

void Node::getNode(int id)
{

}

void Node::acceptedSelection(QString selection, int x, int y)
{
    if(selection=="new node"){


        nodeInfo temp;
        temp.x = y;
        temp.y = x;
        temp.width = 40;
        temp.height = 30;

        nodeMap.append(temp);
        int id = nodeMap.size() - 1;
        qDebug()<<"nodeCalled";
        QString data = "hello";
        generateNode(id);

    }

}

void Node::generateNode(int id)
{
    QString xpos = QString::number(nodeMap[id].x);
    QString ypos = QString::number(nodeMap[id].y);
    QString width = QString::number(nodeMap[id].width);
    QString height = QString::number(nodeMap[id].width);
    QString nodeData = QString("import QtQuick 2.0; Rectangle{x:%1;y:%2;width:%3;height:%4}").arg(
                xpos,ypos,width,height);
    qDebug()<<"generate called";
    emit createNode(nodeData);
}

search.h, за которым следует search.cpp

#ifndef SEARCH_H
#define SEARCH_H

#include <QObject>
#include <QQmlComponent>
#include <QQmlEngine>
#include <QVector>
#include <string>

using namespace std;

class Search:public QObject
{
    Q_OBJECT

public:
    Search(QObject * parent = nullptr);

    Q_INVOKABLE void searchBox(QString txt);
    Q_INVOKABLE QString getSuggestions(int pos);
    Q_INVOKABLE int getSelection();

    int match(QString arg,QString reference);
    void arrange(int ar[],int ar_len);
    int suggestionsMax = 5;

private:
    QVector<QString> suggestions;
    string userFunctions[10] = {"new node","relationship","note","frame","create set","move node","format menu","copy format","paste format","zone"};
    QString inputBuffer;
    int matches[10];
    int currentSelection = 0;
    int suggestionsAvailable = 5;

signals:
    void boxUpdated(QVector<QString> suggestions,int empty);
    void boxHide();
    void spacebarPressed();
    void cycleSelection();
public slots:

};

#endif // SEARCH_H

//search.cpp
#include "search.h"
#include <QDebug>
#include <bits/stdc++.h>
#include <node.h>

Search::Search(QObject * parent):
    QObject (parent)
{

}


//searchBox: parent function for generating suggestions in the suggestion box.
/*
 * This function is called each time the user types in a character, backspaces, or does anything to edit the text in the
 * search bar.
 *
 * input: Qstring txt
 * User input.
 *
 * Action: uses Search::match to match txt to userFunctions, sorts userFunctions in order of decreasing match value using
 * Search::arrange, appends userFunctions to suggestions array, emits signal notifying QML that suggestions has been updated.
*/
void Search::searchBox(QString txt)
{
    int txtlength = txt.size();
    int bufferlength = inputBuffer.size();
    //Compare buffer vs new input: see if user extended input or pressed backspace.
    if(txtlength>bufferlength){
        //if the user extended the input, did the user press spacebar? if yes, push selection
        if(txt[txtlength-1] == " "){
            //Has the selection reached the end of the list? if not, continue pushing selection down
            if(currentSelection<suggestionsAvailable-1){
                currentSelection+=1;
                //this signal simply tells QML to visually move the selection box.
                emit spacebarPressed();
            }
            //the selection has reached the end of the list. restart selection from 0.
            else{
                currentSelection = 0;
                //This signal tells QML to reset selection box to top position.
                emit cycleSelection();
            }
        }
        //if user continues typing after inputing spacebar, reset selection to default position
        //this means the user intended to use spacebar as spacebar rather than to cycle selection.
        else{
            emit cycleSelection();
            currentSelection = 0;
        }
    }
    //If user presses backspace, reset selection to default position
    //user doesn't want to select anything on the current list. Reset selection to default.
    else{
        emit cycleSelection();
        currentSelection = 0;
    }
    //set buffer in preparation for next call. Reset empty to default value.
    inputBuffer = txt;
    int empty = 0;

    //is there anything in txt? if yes, begin analyzing txt.
    if(txtlength!=0){
        int n = sizeof(userFunctions)/sizeof(*userFunctions);

        //see how much txt matches with each userFunction. Values stored in matches[]
        for(int i=0; i<n; i++){
            matches[i]=match(txt,QString::fromStdString(userFunctions[i]));
        }
        //arrange in order of descent; greatest first.
        arrange(matches,n);
        //Reset suggestions from previous appends.
        suggestions = {};

        //Select first 5 suggestions to place on suggest box.
        //This works because suggestions are already ordered from best match to least match.
        //If first five contains suggestions that are low match, exclude these.
        for(int i=0; i<5; i++){
            if(matches[i]>5){
                suggestions.append(QString::fromStdString(userFunctions[i]));
            }
            else{
                empty+=1;
                suggestions.append("");
            }

        }
        suggestionsAvailable = suggestionsMax-empty;
        emit boxUpdated(suggestions,empty);
    }
    //if user preses backspace and clears the search box: clear suggestions
    else{
        suggestions = {"","","","",""};
        empty = suggestionsMax;
        suggestionsAvailable = 0;
        emit boxUpdated(suggestions,empty);
        emit boxHide();
    }
}

int Search::getSelection()
{
    return(currentSelection);
}

//This function swaps values held by two pointers.
void swap(int *xp, int *yp)
{
    int temp = *xp;
    *xp = *yp;
    *yp = temp;
}

/*
 * Sorting algorithm. selective sorting method
 * Sorts provided array in descending magnitude. The sorting of userFunctions is coupled to this process.
*/
void Search::arrange(int ar[],int ar_len)
{
    int n = ar_len;

    int flag  = 0;
    for(int i = 0; i<n-1; i++){
        flag = i;
        for(int j = i+1; j<n; j++){
            if(ar[j]>ar[flag]){
                flag=j;
            }
        }
        swap(&ar[flag],&ar[i]);
        string temp;
        temp = userFunctions[flag];
        userFunctions[flag] = userFunctions[i];
        userFunctions[i] = temp;
    }


    for(int i=0;i<n;i++)
    {
        matches[i] = ar[i];
    }
}

//fetches suggestions. Called from QML.
QString Search::getSuggestions(int pos)
{
    return suggestions[pos];
}


//This function takes two strings, and sees how much the first string matches the second string.
/*
 * input: string1, string2
 * output: integer
 *
 * The higher the integer, the higher the match.
*/
int Search::match(QString arg,QString reference)
{
    int temp = 0;
    int l = arg.size();
    \
    QStringList split;
    for(int i=l; i>0; i--){
        QString sub = arg.mid(0,i);
        \
        if(reference.contains(sub)){
            temp+=i*i;
        }
        split = reference.split(" ");
        int s = split.size();
      \
        for(int j=0; j<s; j++){

            QString spsub = split[j].mid(0,i);
            if(sub==spsub){

                temp+=i*i;
                if(j==0){
                    temp+=5;
                }
            }
        }
    }
    return temp;
}


main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQmlComponent>
#include <QQmlEngine>
#include <QObject>
#include <search.h>
#include <node.h>




int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);


    QQmlApplicationEngine engine;
    qmlRegisterType<Search>("Search",1,0,"Search");
    qmlRegisterType<Node>("Node",1,0,"Node");

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}
``

1 Ответ

0 голосов
/ 31 октября 2019

Вы создаете Node динамически через find свойство myitem . Нет связи с этим узлом. Этот узел отличается от того, что вы ожидаете испускать этот сигнал.

Вот свойство find, чтобы проверить, сработал ли сигнал:

   property string find:"
        import QtQuick 2.0
        import Search 1.0
        import Node 1.0
        FocusScope{
            id: scope;
            focus:true;
            x:%1;
            y:%2;

            Rectangle {
                id: suggestionBox;
                color: 'grey';
                border.width:2;
                width:200;
                height:135;
                x:-5000
                y:34
                Text {
                    id: first;
                    x: 5;
                    y: 5;
                    text: '';
                }
                Text {
                    id: second;
                    x: 5;
                    y: 30;
                    text: '';
                }
                Text {
                    id: third;
                    x: 5;
                    y: 55;
                    text: '';
                }
                Text {
                    id: fourth;
                    x: 5;
                    y: 80;
                    text: '';
                }
                Text {
                    id: fith;
                    x: 5;
                    y: 105;
                    text: '';
                }
                Rectangle {
                    id: selectionBox;
                    color:'#33000000';
                    border.width:2;
                    width: 200;
                    height:25;
                    x: 0;
                    y: 0;
                }
            }

            Rectangle {
                id:newrect;
                color: 'grey';
                border.width: 4;
                width: 200;
                height: 30;
                focus:true;

                x:0;
                y:0;
                Node {
                    id: node;


                }
                Search {
                    id: search;
                }
////////////////////////////////////////////////
// HERE I ADDED THE CONNECTION TO TEST THE SIGNAL
////////////////////////////////////////////////
        Connections {
            id: nodeconnect;
            target: node;
            onCreateNode:{
                console.log(\"hi\");
            }
        }

                Connections {
                    id: searchconnect
                    target: search;
                    onBoxHide: {
                        suggestionBox.x = -10000;
                    }
                    onBoxUpdated: {
                        suggestionBox.height = (5-empty)*27;
                        suggestionBox.x = 0;
                        first.text = search.getSuggestions(0)
                        second.text = search.getSuggestions(1)
                        third.text = search.getSuggestions(2)
                        fourth.text = search.getSuggestions(3)
                        fith.text = search.getSuggestions(4)

                    }
                    onSpacebarPressed: {
                        selectionBox.y = selectionBox.y + 25;
                    }
                    onCycleSelection: {
                        selectionBox.y = 0;
                    }
                }
                property int xbuffer: %3;
                property int ybuffer: %4;

                TextInput {
                    id: input;
                    focus: true;
                    x:5;

                    y:5;

                    onTextChanged: {
                        search.searchBox(input.text)

                    }

                    onAccepted: {

                        node.acceptedSelection(search.getSuggestions(search.getSelection()),newrect.xbuffer,newrect.ybuffer);
                        scope.x = -400;
                        scope.y = -100;

                    }

                }
                Component.onCompleted:{
                    input.forceActiveFocus();
                }

            }
        }"
...