Отправка сигнала элементу QML из C++ (Qt5)
у меня есть файл QML, содержащий это:
Text {
id: testData
onTaskClicked:{
testData.text = task.name
}
}
уловка - это сигнал taskClicked. Он испускается другим виджетом (C++) и должен быть передан в QML.
это похоже на это так вопрос, за исключением того, что решение опубликовано здесь не работает (почему-написано ниже).
код C++:
ctxt->setContextProperty(QLatin1Literal("holiday"), m_model);
ctxt->setContextProperty(QLatin1Literal("bgcolor"), color);
view->setResizeMode(QQuickView::SizeRootObjectToView);
auto mainPath = QStandardPaths::locate(QStandardPaths::DataLocation,
QLatin1Literal("taskview.qml"));
view->setSource(QUrl::fromLocalFile(mainPath));
ctxt->setContextProperty(QLatin1Literal("viewer"), m_view);
m_view
это QListView
подкласс, который выдает taskClicked(HolidayTask* task)
сигнала (от .ч файл):
Q_SIGNALS:
void taskClicked(HolidayTask* task);
color
и m_model
зарегистрированы в QML и используются в других местах. Объект из сигнала уже зарегистрирован в QML. view
мой QQuickView
.
сначала я попробовал решение, представленное в вопросе выше:
auto root = view->rootObject();
auto myElement = root->findChild<QObject*>(QLatin1Literal("testData");
connect(m_view, SIGNAL(taskClicked(HolidayTask* task), myElement,
SLOT(taskClicked(HolidayTask* task);
, myElement
всегда равно null (и я получаю предупреждение во время выполнения о несуществующем слоте).
если я попытаюсь установить указатель view (QListView) в качестве свойства контекста представления QML, он все еще не работает.
во всех случаях я получаю также:
QML Connections: Cannot assign to non-existent property "onTaskClicked"
что я могу здесь делать не так?
изменить, чтобы уточнить некоторые детали: HolidayTask
является пользовательским подклассом QObject и сигналом taskClicked
определяется в C++ (в A QListView
подкласс)
EDIT2: мы приближаемся, но нет сигары:
auto root = quickView->rootObject();
auto myElement = root->findChild<QObject*>(QLatin1Literal("testData"));
connect(m_view, SIGNAL(taskClicked(HolidayTask*)),
myElement, SIGNAL(taskClicked(HolidayTask* task)));
и
Text {
id: testData
objectName: "testData"
signal taskClicked(HolidayTask task)
onTaskClicked: {
testData.text = task.name
console.log("CLICk!")
}
}
доходность
QObject::connect: No such signal QQuickText_QML_0::taskClicked(HolidayTask* task) in /home/lb/Coding/cpp/holiday-planner/src/mainwindow.cpp:178
QObject::connect: (receiver name: 'testData')
больше деталей: HolidayTask, моя таможня Подкласс QObject, зарегистрирован в коде как
qmlRegisterType<HolidayTask>("HolidayPlanner", 1, 0, "HolidayTask");
минимальный QML с данными:
import QtQuick 2.0
import QtQml 2.2
import HolidayPlanner 1.0
Rectangle {
id: container
objectName: "container"
color: bgcolor
Text {
id: testData
objectName: "testData"
signal taskClicked(HolidayTask task)
onTaskClicked: {
testData.text = task.name
console.log("CLICK")
}
}
}
EDIT3: окончательный, рабочий код (см. ответы на почему)
connect(m_view, SIGNAL(taskClicked(HolidayPlanner::HolidayTask*)),
myElement, SIGNAL(taskClicked(HolidayPlanner::HolidayTask*)));
он работал только через использование объектов с полными пространствами имен. В противном случае подпись не будет совпадать в QML.
3 ответов
однако,
myElement
всегда null (и я получаю предупреждение о времени выполнения несуществующий слот).
вы пытаетесь найти ребенка на основе id, тогда как он основан на свойстве objectName. Вам нужно будет установить свойство objectName на желаемое, чтобы фактически найти его.
кроме того, вы, похоже, не объявляете сигнал в текстовом элементе QML. Я не уверен, является ли это пользовательским элементом C++ или встроенным. Вы не достаточно код к сожалению, понять это немного. В любом случае, объявите свой сигнал согласно документации.
поэтому, попробуйте этот код:
Text {
id: testData
objectName: "testData"
// ^^^^^^^^^^^^^^^^^^^
signal taskClicked (HolidayTask task)
// ^^^^^^^^^^^^^^^^^^^
onTaskClicked:{
testData.text = task.name
}
}
как только это будет сделано, вы почти готовы. Вы должны иметь свой HolidayTask зарегистрирован на QML точно,и вы также должны изменить синтаксис подключения в вашем основном.СРР следующим образом:
connect(m_view, SIGNAL(taskClicked(HolidayTask* task), myElement, SIGNAL(taskClicked(HolidayTask* task)));
короче говоря, вам нужно вызвать обработчик сигнала QML таким образом, а не через SLOT
.
также, обратите внимание, что синтаксис connect нарушен, поскольку в нем отсутствуют заключительные скобки в конце. Это нужно исправить.
Я бы даже рассмотрел удаление назначения указателя и использование значения или ссылки на основе передачи для этого.
вы можете подключить сигнал с C++ на QML по:
view->rootContext()->setContextProperty("testData",this);
QObject::connect(this,SIGNAL(taskClicked(HolidayTask* task)),(QObject *)view->rootObject(),SLOT(onTaskClicked(HolidayTask* task)));
когда ваш сигнал называется taskClicked
слот в QML должен быть onTaskClicked
.
также в QML, вы должны назвать объект testData
by:
objectName: "testData"
QML Connections: Cannot assign to non-existent property "onTaskClicked"
ошибка говорит вам, что ваш Text
деталь не имеет сигнал taskClicked
или собственность onTaskClicked
!
Нужно объявить слот внутри вашего текста. Для этого вы просто объявляете функцию:
Text {
id: testData
objectName: "testData" // as Laszlo said
function onTaskClicked( task ) {
testData.text = task.name;
}
}
но это также не будет работать, потому что вы создаете SLOT( onTaskClicked(QVariant) )
вместо SLOT(taskClicked(HolidayTask*))
. Для обмена данными с QML необходимо изменить сигнал на SIGNAL(taskClicked(QVariant))
:
Q_SIGNALS:
void taskClicked(QVariant task);
и испускают его с:
emit taskClicked( QVariant::fromValue( task ) );
помните, что для того, чтобы уметь использовать HolidayTask
должно быть QObject
, зарегистрированного с qmlRegisterType
.
вы можете просто вызовите эту функцию qml.
если вы не можете использовать QVariant, вы можете объявить сигнал внутри текстового объекта:
Text {
id: testData
objectName: "testData" // as Laszlo said
signal taskClicked ( HolidayTask task )
onTaskClicked: {
testData.text = task.name;
}
}
а затем подключиться от сигнала C++ к сигналу qml:
auto root = view->rootObject();
auto myElement = root->findChild<QObject*>(QLatin1Literal("testData");
connect(m_view, SIGNAL(taskClicked(HolidayTask*), myElement,
SIGNAL(taskClicked(HolidayTask*));