I've got following code:
main.cpp
QDeclarativeView *qmlView = new QDeclarativeView();
qmlView->setSource(QUrl("qrc:/nav.qml"));
ui->nav->addWidget(qmlView);
Blockschaltbild bild;
QObject *value = qmlView->rootObject();
QObject::connect(value, SIGNAL(testSig()), &bild, SLOT(BlockSlot()));
The signals and slots connect correctly. (QObject::connect returns "true")
qml file:
Rectangle {
id: rectangle1
....
signal testSig()
MouseArea{
id: mousearea
anchors.fill: parent
onEntered: parent.color = onHoverColor
onExited: parent.color = parent.buttonColor
onClicked: {
rectangle1.testSig()
console.log("Button clicked")
}
}
}
This is where the slot is located:
Blockschaltbild.h
class Blockschaltbild: public QObject
{
Q_OBJECT
public slots:
void BlockSlot(){
cout << "Slot is working" << endl;
}
public:
....
}
If I click on the mouse area, the console shows "Button clicked" but not "Slot is working".
I use Qt 4.8.4 with QtQuick 1.1. Where is my mistake?
If you simply require to work with your Blockschaltbild object in QML, you can also decide against a loose coupling with signal and slots and simply pass your object as a context parameter, to make it available in QML.
QDeclarativeView *qmlView = new QDeclarativeView();
qmlView->setSource(QUrl("qrc:/nav.qml"));
ui->nav->addWidget(qmlView);
Blockschaltbild* bild;
QObject *value = qmlView->engine().rootContext()->setContextProperty("bild", bild);
You can then call the BlockSlot() slot of your object from QML with:
Rectangle {
id: rectangle1
....
MouseArea{
id: mousearea
anchors.fill: parent
onEntered: parent.color = onHoverColor
onExited: parent.color = parent.buttonColor
onClicked: {
bild.BlockSlot() // call BlockSlot of "bild" context property
console.log("Button clicked")
}
}
}
It is also possible to use qmlRegisterType, which allows you to create instances of your Blockschaltbild class with QML. See here for more information.
Related
I have a QML ListView and I want to access to the delegate children in c++
main.qml
ApplicationWindow {
objectName: "wnd1"
ListView {
objectName: "mediaPlayerListView"
model: provider.mediaPlayerItems
delegate: MediaPlayerDelegate
}
}
MediaPlayerDelegate.qml
Row {
objectName: "mainRow"
VideoOutput {
objectName: "videoOutput" + modelData.id
}
Here is the c++ code I've tried
QString currentId = "1";
QQuickWindow *mainWindow = _qmlAppEngine->rootObjects()[0]->findChild<QQuickWindow *>("wnd1");
QObject *mediaPlayerListView = mainWindow->findChild<QObject *>("mediaPlayerListView");
QObject *mediaPlayerListViewDelegate = mediaPlayerListView->property("delegate").value<QObject *>();
I want to be able to get in cpp the videoOutput, doing something like this
QObject *videoOutput = mediaPlayerListViewDelegate->findChild<QObject *>("videoOutput" + currentId)
But I can't access further than the delegate, it has no children.
I am using a QQuickWindow, QQuickRenderControl, and a QOffscreenSurface to render a Qml scene into an OpenGL framebuffer object.For this reason, I am using qt example Qt/Examples/Qt-5.15.2/quick/rendercontrol as a base with some minor modifications.
Since no window is actually created, it becomes necessary to artificially transfer mouse and keyboard events to QQuickWindow.There was already mousePressEvent example for mouseEvents on renderControl example which works fine that means I can send mouse events to qml.
Similarly, I tried to implement keyPressEvent and keyReleaseEvent by using QCoreApplication:: sendEvent (m_quickWindow, e); function call but it does not send key events to qml even if I set force to true for a rectangle. When I debug the issue, I have observed that activeFocusItem is NULL on qquickwindow.cpp ==> deliverKeyEvent function.
After that, I put a mousearea inside rectangle and call forceActiveFocus() function for rectangle and then keyPressEvent are sent to qml successfully.Also, If I put timer and call forceActiveFocus for rectangle on some interval it also works but If I try to call same forceActiveFocus() function on Component.onCompleted it is not sending any key events to qml.
So Do I have to call forceActiveFocus() to manage key sending for offscreen surface? Also if I have to call forceActiveFocus() from qml, then is there any way to call it instead of timer or mousearea?
Following is my code snippets:
import QtQuick 2.5
import QtQuick.Window 2.2
Rectangle {
visible: true
width: 1280
height: 480
color: "#000"
Rectangle
{
id:keyPressRect
width:100
height: 100
//focus: true
color: activeFocus? "red": "blue"
onFocusChanged: console.log("focus changed to: " + focus)
onActiveFocusChanged: console.log("active focus changed to: " +activeFocus)
Component.onCompleted:
{
console.log("onCompleted(), focus: " + focus + " activeFocus: " + activeFocus)
forceActiveFocus()
console.log("onCompleted(), focus: " + focus + " activeFocus: " + activeFocus)
}
/*Component.onCompleted: mTimer.start()
Timer {
id:mTimer
interval: 5000
repeat: false
onTriggered: {
keyPressRect.forceActiveFocus()
console.log("testtt")
}
}*/
Keys.onPressed:
{
console.log("key pressed on qml")
}
Keys.onReleased:
{
console.log("key released on qml")
}
MouseArea
{
anchors.fill: parent
onClicked:
{
parent.forceActiveFocus()
console.log("mouse clicked")
}
}
}
}
And sending keyPressEvent from C++ as the following:
void WindowSingleThreaded::keyPressEvent(QKeyEvent *e)
{
qDebug() << "key press event from cpp";
qDebug() << e->key() << "key is";
QCoreApplication::sendEvent(m_quickWindow, e);
}
I need to write a GrabWindow, so I derived my class GrabWindow from QQuickWindow:
#include <QtQuickWidgets/QtQuickWidgets>
#include <QString>
class GrabWindow : public QQuickWindow {
Q_OBJECT
public:
explicit GrabWindow(QQuickWindow *parent = nullptr);
public slots:
void capture(QString const &path);
};
// .CPP
#include "grab_window.h"
#include <QImage>
GrabWindow::GrabWindow(QQuickWindow *parent) : QQuickWindow(parent) {
}
void GrabWindow::capture(const QString &path) {
QImage img = this->grabWindow();
img.save(path);
}
After I registered it in QML: qmlRegisterType<GrabWindow>("myapp", 1, 0, "GrabWindow");
And after I defined my window in QML:
import QtQuick 2.4
import QtQuick.Controls 2.2
import QtQuick.Window 2.3
import myapp 1.0
GrabWindow {
id : translationWindow
width : 1024
height : 768
color: "transparent"
visibility: "FullScreen"
visible: true;
signal capture(string path)
MouseArea {
anchors.fill: parent
onClicked: translationWindow.capture("/home/user/saveTest.jpg")
}
}
But it doesn't show on start (I know it's transparent, I mean the grab window doesn't start to show). If instead of GrabWindow I use Window or ApplicationWindow then all works perfectly I am seeing a transparent full-screen window.
What's wrong?
Your GrabWindow is not shown because when you are setting the visible property it's not same as when you use Window's visible property.
Yours is just the visible property of QWindow.
Window does not directly instantiate QQuickWindow, it instantiates a private Qt class QQuickWindowImpl which overrides the visible property with a custom one.
It seems to delay the actual call of the QWindow::setVisible at a later time.
As such, I don't think QQuickWindow is meant to be inherited from. You could try doing visible = true in your Component.onCompleted but I'm not sure it will resolve your problem.
What I would advise you instead is not subclassing QQuickWindow but just creating a new type and pass it the existing Window.
Possible API could be :
Window {
id: myWindow
//...
MouseArea {
anchors.fill: parent
onClicked: WindowGrabber.grab(myWindow, path) //singleton type
}
}
or
Window {
id: myWindow
//...
WindowGrabber { // regular type
id: windowGrabber
window: myWindow
}
MouseArea {
anchors.fill: parent
onClicked: windowGrabber.grab(path) // you could even add a path property in WindowGrabber and not have it as a function parameter if that makes sense for your use case
}
}
I have a painful issue in QT5 using QQuickItem. I had to draw a 3D model using pure openGL in QML, so I created my own custom QQuickItem. Untill now everything works as expected: the 3D model is beautifully displayed in QML.
The problem appears when I want to put a simple Rectangle in the same QML beside my custom QQuickItem. The 3D model is no longer displayed. Why is that?
Here is my custom quick item code:
MQuickItem::MQuickItem(){
isInit = false;
connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*)));
}
void MQuickItem::handleWindowChanged(QQuickWindow *win){
w = new SMThickness3DView(/*width(), height()*/);
if(win){
connect(win, SIGNAL(sceneGraphInitialized()), this, SLOT(initializeMGL()), Qt::DirectConnection);
connect(win, SIGNAL(beforeRendering()), this, SLOT(paintMGL()), Qt::DirectConnection);
connect(win, SIGNAL(widthChanged(int)), this, SLOT(resizeMGL()), Qt::DirectConnection);
connect(win, SIGNAL(heightChanged(int)), this, SLOT(resizeMGL()), Qt::DirectConnection);
win->setClearBeforeRendering(false);
}
}
void MQuickItem::initializeMGL(){
w->initializeGL();
isInit = true;
}
void MQuickItem::paintMGL(){
w->paintGL();
// connect(window()->openglContext(), SIGNAL(aboutToBeDestroyed()), this, SLOT(cleanupMGL()), Qt::DirectConnection);
}
void MQuickItem::resizeMGL(){
if(isInit){
w->resizeGL(width(), height());
w->paintGL();
}
}
void MQuickItem::cleanupMGL(){
}
void MQuickItem::rotatePerson(bool toLeft){
if(toLeft)
w->setYaw(std::min(w->getYaw() + 2., 90.));
else
w->setYaw(std::max(w->getYaw() - 2.0, -90.0));
}
And here is my QML with a small rectangle over the 3D model:
Item {
anchors.fill: parent
anchors.centerIn: parent
MQuickItem {
id: obj
property bool mReleased: true
anchors.fill: parent
MouseArea{
id: mArea
anchors.fill: parent
drag.target: dummy
property int initialPressedX;
property int initialPressedY;
onPressed: {
initialPressedX = mArea.mouseX;
initialPressedY = mArea.mouseY;
}
onPositionChanged: {
var diff = mArea.mouseX - initialPressedX;
if(Math.abs(diff) > 10){
if(diff < 0){
obj.rotatePerson(false)
}
else{
obj.rotatePerson(true)
}
initialPressedX = mArea.mouseX;
initialPressedY = mArea.mouseY;
}
}
Rectangle{id: dummy}
}
}
Rectangle{
id:thisIsTheRectangleThatMakesMyModelDisapear
width: 50
height: 50
color:"red"
}
}
Can anyone provide me with at least an explanation of this issue, or some suggestions?
I have a QML plugin which has a QThread inside. It is used to capture and display videoframes into the QMLview.
The problem is: how can I stop this thread when the window is closed?
QML
Repeater {
model: 8
CVCamScreen {
Layout.fillWidth: true
Layout.fillHeight: true
url: Controller.urlCanal(index + 1)
CustomBorder {
commonBorder: true
color: "#228e14"
commonBorderWidth: 3
}
}
}
C++ Component
class CVCamScreen : public QQuickPaintedItem
{
CVCamScreen::CVCamScreen(QQuickItem *parent):
QQuickPaintedItem(parent)
{
m_worker = new CamWorker(this);
}
CVCamScreen::~CVCamScreen()
{
m_worker->stop();
delete m_worker;
}
private:
CamWorker* m_worker; // inherits from QThread;
}
The current behavior is: the thread keeps running after the window is closed which means the CVCamScreen instances are not being destroyed.