How to expose a C++ visual element to QML - qt

"I want to draw my visual item object that created in c++ in qml."
current state.
I wrote a subclass of QQuickFramebufferObject in C++.
and it renders something using its renderer. so I think that is visual item.
I register the subclass through qmlRegisterType() for using it in QML.
I instanciated the class object in QML and set area to draw something.
After the engine loads qml, I find the object which made in QML and put it into a pointer in C++.
so that I can add data with the pointer and that updates in QML.
It is working well. rendering data on proper area.
problem I got.
I am using StackView element for navigation, and when I move to other view and comeback.
It seems QML instances in prev view are re-created, so my connections with C++ be invalidated.
solution I thought
I am not sure, that is right way or not. Anyway I tried to instanciate the object in C++ not in QML.
and register it to QML through setContextProperty().
and set parent, render area for that property, but it is not working the object do not render anything.
code outline is below
// in C++
mCustomWidget = new CustomWidget;
engine->rootContext()->setContextProperty("custom_widget", mCustomWidget);
// in QML
Item { // CustomContainer
id: container
Component.onCompleted: custom_widget.parent = container
onXChanged: custom_widget.x = x
onYChanged: custom_widget.y = y
onWidthChanged: custom_widget.width = width
onHeightChanged: custom_widget.height = height
}
I expected C++ side has the object so it would be not deleted whether move to other view or not.
With the pointer in QML side which is context property name, I can see the rendered results if I set its parent and render area.
but, It is something wrong so not working.
Please, let me know the wrong points or other solution. I would be appreciated it. Thank you.

Related

how the QtObject element works in QML

I just want to know what this QtObject elements does, its seems that is reactive, because in the tutorial that I followed, use it for update the color of a button, so, I want to know how I can use it, and how its works, and how I can use in other cases.
while your are working on QML file need to hide some properties from upper layer Item ( some thing's like private variable and methods).
best case for get a right way for incapsulation in QML is to using a internal item like QtObject .
in your code used a QtObject for block the external direct access to button color and bind the color to the button item state.
I assume you've read the docs? A QtObject is just the most basic type of of QML object. It doesn't do anything by itself. It's not visual. So it's just used for holding other properties.
In the example you provided, it's being used as a way to make pseudo-private variables. QML has no such thing as private variables, but if you put properties inside of an object, then they are not accessible to anything outside of this file (unless explicitly exposed). That's all it's being used for in your example. If you took the property dynamicColor and moved it outside of the QtObject, the code would still work exactly the same way. The only difference would be other QML files would be able to access (and therefore modify) dynamicColor.

What's the purpose of auto added QLayout with objectName '_layout'

I was exploring Qt layouts and widget management and have come across the behaviour I can't explain.
I have a base UI with the following hierarchy:
MainWindow(QMainWindow) ->
centralwidget (QWidget),
menubar(QMenuBar),
statusbar(QStatusBar)
Later I add several layouts and widgets to the centralwidget, but, I beleive, it's not important in this context.
Now, if we check MainWindow's children objects and their objectNames we will see the following:
<PyQt5.QtWidgets.QLayout object at 0x00000000089425E8> _layout
<PyQt5.QtWidgets.QWidget object at 0x00000000087C6F78> centralwidget
<PyQt5.QtWidgets.QMenuBar object at 0x0000000008942048> menubar
<PyQt5.QtWidgets.QStatusBar object at 0x00000000089420D8> statusbar
For some reason, a QLayout object _layout appears. But this is not all. It seems to me that this QLayout is not persistent and, occasionally, is being added and removed, for example on resize. I have added an eventFilter for a resize event, and here are the object addresses after several window resizes:
<PyQt5.QtWidgets.QLayout object at 0x0000000008942708> _layout
<PyQt5.QtWidgets.QLayout object at 0x00000000089425E8> _layout
<PyQt5.QtWidgets.QLayout object at 0x0000000008942798> _layout
<PyQt5.QtWidgets.QLayout object at 0x00000000089428B8> _layout
The layout is there, but every time the object is new.
What's going on here? What's the purpose of this QLayout, and why it behaves this way?
The QMainWindow class has a built-in custom layout that manages all the toolbars, menubars, dock-widgets, statusbar and central-widget area:
This layout cannot be removed, or replaced by a different layout. If you try to do that, Qt will complain (or possibly even crash).
The object id shown in the repr doesn't mean much. This is the id of the PyQt wrapper for the layout and not the memory address of the underlying C++ object. The layout is actually a QMainWindowLayout - but that is not a public type, so PyQt can only return a QLayout (which is its base-class). It is likely that PyQt is returning a new wrapper around the same underlying C++ object every time you access it.

How to replace all cursor appearances within a QML program?

I'm working on a game that uses QML for its UI.
I would like to replace all cursors appearances with cursor-images that are more fitting to the game style (e.g. pointing skeleton hand instead of the normal Qt::ArrowCursor).
Calling QGuiApplication::setOverrideCursor() seams not to be a practical solution as I can not "overwrite" each MouseArea to call may replaceCursor() magic-global-function. For example the change column with cursor within a TableView is currently impossible for me to manipulate.
To me the most practical solution would be to replace the appearance of all cursors but leaf Qt with the tasks to correctly choose the cursor style.
Thanks for any help!
You can still use QGuiApplication::setOverrideCursor() to decorate your mouse areas. It works like a stack, you can set and then restore cursors, so you begin with setting an initial cursor from main.cpp, and then you use an "overloaded" MouseArea which sets its cursor using setOverrideCursor() as well, instead of using the QML functionality.
For example:
onContainsMouseChanged: {
if (containsMouse) Sys.setOverrideCursor(yourCursortype)
else Sys.restoreOverrideCursor()
}
Of course, that means you will have to create an auxiliary object that will call those functions from C++, and expose it to QML so it can be called from there.

How to scroll QLabel?

I am trying to implement Picture Zoom In/Out and Picture Scroll on Meego/Qt/QML.
I have written a class A which is inherited from QLabel.
A::A( "parent" )
{
setAlignment();
setGeometry();
setScaledContents();
}
Now I have a Controller class B. This class is responsible to handle the events from QML to the my Class A. In my controller class I have instantiate in the following way.
B :: B()
{
a = new A();
proxyWidget = new QGraphicsProxyWidget();
proxyWidget->setWidget(a);
}
Since this is a QML based application I am handling events from QML.
For Zoom I have used PinchArea. Whenever I am getting PinchUpdated event I am setting the setGeometryof the QLabel accordingly. I am zooming in and zooming out.
For scroll I have used MouseArea with onPositionChanged event. However I am unable to scroll the label event after calling the scroll API of the QLabel.
Can someone please tell me where am I doing wrong?
I assume you want to zoom using mouse scroll for instance.
I am not good at QML but you certainly should be handling wheel events in your class A. It is not clear for me if every Qt event has a QML equivalent, but you can always put C++ code. The function to implement is :
virtual void wheelEvent ( QWheelEvent * event );
You have the delta variable which can be useful to determine the speed of zoom (using delta absolute value) and whether it should grow or shrink (using sign of delta)

OpenGL rendering to a QML item

I have a QML file which contains a layout of QML items and now I want one of those items to be a QGLWidget. i.e. I want to render to a specific QML item.
Is anyone aware of how to do this?
The simplest way I suppose it to provide QML a new custom component implemented in C++. I couldn't find anything ready.
You could subclass the QDeclarativeItem and implement your OpenGL code in the paint function after using the QPainter::beginNative() function. After that you can "export" your new custom item to QML this way. This is quite simple and should work, but you'll have to setup the viewport of you QDeclarativeView to be a QGLWidget, something like this:
QDeclarativeView view;
// This is needed because OpenGL viewport doesn't support partial updates.
view.setViewportUpdateMode(QGraphicsView::FullViewportUpdateMode);
view.setViewport(new QGLWidget);
or you'll have to use the opengl graphics system for the entire application.
Another way is using QML/3D.
This thread will give you some other information.

Resources