How to find if QuickItem is topmost in QmlScene (z-order)? - c++

Currently I am developing in Qt / Qml, using QtQuick.
I came to a point, where I need to find out, if an item of my scene is topmost. That is, I need to find if the item has the highest z-coordinate.
I tried to build an algorithm, using childAt and mapToScene. It turned out, that this is horribly slow. Then I found out about itemAt(). Unfortunately, it is only available in GraphicScene, i.e. in the widget world.
Now my question: Is there an equivalent to itemAt() in the QmlSceneGraph? How can I find out, if an item is the topmost one? I do not even need the exact z-order, just to make sure, the item is displayed at top.
Thanks for your help.
Greetings from Germany

You can use Item::childAt(real x,real y) method
ApplicationWindow {
id: root
visible: true
MouseArea {
anchors.fill: parent
onClicked: console.log(root.contentItem.childAt(mouse.x,mouse.y));
}
}

Related

Detect when mouse hover an ui element other than Scene3D QML

I have a Qt3D application with a Scene3D QML object taht is used to render my 3D scene only, on top of that i have regular 2D qml item/objects to render my ui.
I want to modify the cursor's shape whenever the user is hovering on the 3d scene only, and to reset the cursor when he is entering any 2d widget.
Is there an elegant way of doing this ? I've tried to add a MouseArea on the Scene3D but this doesn't work. Or to add one after all the other so that it is the last to catch mouse events, but if I understand correctly that would mean that I would have to go back and add MouseArea to every QML component that I have.
Thank you for your help.
I do not know what is your problem (as you posted no code) but following simple MouseArea (in Rectangle where the scene view is) seems to work for me:
MouseArea {
hoverEnabled: true
anchors.fill: parent
cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
}
That resets back to ArrowCursor just fine.

Create a Grid Layout Dynamically and manage it in Qt

I'm new in Qt and currently I'm having some trouble. I want to create a grid layout in Qt from the c++ code and to be able to manage it from there. I have tried many different things but none of them work.
Basically, what I want to do is to have a window with a button in it(done that), and by pressing the button the window should change into a grid of buttons with no fixed number of rows or columns. ( hope I was clear on what I want to do)
At this point, I have created two .qml , one qml file has the code for the first window(the one with the one and only button) and the other qml file has a grid layout with nothing in it. There are also two c++ files the first one is the main.cpp and on the second one is the code I am writing to "fill" the grid on the click of the button.
Again, I'm new to Qt so if you have any better ideas please let me know!
You can use a Repeater to create some amount of Buttons as children of the Grid. The Grid will automatically set the positions of the Buttons so you should not set any anchors or coordinates.
To handle the signals, you define one signal somewhere, that you then connect to the buttons signal.
Grid {
id: buttonGrid
signal buttonClicked(int index)
Repeater {
model: 100 // or any integer number
delegate: Button {
onClicked: buttonGrid.buttonClicked(index)
}
}
}
Instead of using a integer model, you might also use e.g a ListModel or any QAbstractItemModel-descendent. Then you can also use their roles, to get stuff like textes or colors or functions...
A simple array with textes would also be possible.

Sending mouse events to a QtQuick window in a virtual reality OpenGL scene

I am currently working on a virtual reality project that builds on OpenGL. Because I also needed some form of user interface, I thought it would be a good idea to integrate QtQuick windows into the scene. Drawing the window to a texture works without problems (I used this example) but I struggle to send mouse events so that my controllers can interact with it.
Here is a quick example video on YouTube. In this example, the animation of the embedded GIF should stop whenever I hover over it. This works in a normal QML application but not when I manually send a MouseMove event.
The mouse position within the window is known (the red line in the video indicates an intersection) and I am currently sending the event through
QQuickWindow::sendEvent(QQuickItem* item, QEvent*)
where item is the root Rectangle in the qml source:
import QtQuick 2.3
import QtQuick.Controls 2.0
Rectangle {
color: mouseArea.containsMouse ? "red" : "white"
width: 600
height: 400
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
AnimatedImage {
anchors.fill: parent
paused: mouseArea.containsMouse
source: "test.gif"
}
}
}
The event, which I send every time an intersection between the ray and the window is found, is done with:
QMouseEvent* mouseMoveEvent = new QMouseEvent(
QEvent::MouseMove, // wrong event?
cursorPosition, cursorPosition, // Note: cursorPosition := the calculated cursor coordinates within the window
Qt::MouseButton::NoButton,
Qt::MouseButtons(), // is this right?
Qt::KeyboardModifier::NoModifier);
window->sendEvent(rootItem, mouseMoveEvent); // Note: window is my QQuickWindow, rootItem is the root Rectangle
I am not an expert in QML (rarely used it) and would appreciate it if someone has suggestions on how to solve this. My guess is, that I am neither using the right event nor correctly sending them.
I found a solution myself. Instead of using QQuickWindow::sendEvent(..) I had to simply use QApplication()::instance()->sendEvent(..).

QDockWidget::background-color not applied when docked

I have a QDockWidget:
I would like to alert the user to certain events by setting the background color of the title bar.
I have achieved this by setting the style sheet for my DockWidget:
void DockWidget::setCriticalAlert()
{
setStyleSheet("QDockWidget { background-color:red; }");
}
The result is this:
The problem is that the background-color doesn't get applied when the QDockWidget is docked:
How can I get the background color to be applied when the QDockWidget is docked?
This is a bug in Qt.
Issue 10537
Quoting from the linked issue:
The problem is that in QDockWidget::paintEvent, there is a
isFloating() condition before drawing PE_FrameDockWidget. We cannot
jsut remove this condition as it would break the other style (that
does not whish to draw frame when the dockwidget is docked) We cannot
either use PE_Widget to draw the frame as then it goes over the
dockwidget's title The solution is maybe to introduce a new
PE_FrameDockWidgetDocked primitive element. Or some
SH_DockWidget_DrawDockedFrame stylehint to draw the frame in every
cases.
a valid workaround seems to be to set the stylesheet of the parent, and use the class-and-id selector. Forgive the python formatted code but the concept is the same - in this case, 'dock' is a QDockWidget which has been given an object name using setObjectName(), and its parent, the QMainWindow, is 'self':
self.setStyleSheet("QDockWidget#"+str(dock.objectName())+"::title {background-color:red}")
In PyQt5.5, this works at runtime, i.e., can be changed on the fly.
I find a solution like this:
Firstly put a frame behind all the widgets of dockwidget's center widget, as the background.
Then set stylesheet for the frame.
By this way, we could change the background color of dockwidget.
Or you can extend the dockwidget and overwrite the function
void QDockWidget::setWidget(QWidget *widget)
using private/qdockwidget_h. and add a frame as this widget's father.

Styling QListWidget item widgets: selected state

I have a window which displays tiles, each tile having some set of information. Tiles are arranged in a tabular structure. The way in which this is implemented is, a QListWidget is used to hold tiles and each tile is set as the item widget in QListWidgetItems in QListWidget.
I have styled the tiles using a stylesheet. My problem is, I cannot get a tile highlighted in some way when the tile is selected. If I do not use stylesheets at all, default selected highlighting works. But as soon as I apply styles to tiles, there is no difference in the tile in non selected and selected states.
I tried to do it in following way but it does not work.
.tile
{
/*non selected style*/
}
.tileList::item:selected
.tile
{
/*selected style*/
}
Any idea how I can achieve this?
I solved it in Qt Designer by setting the palette how I wanted it and then put
QListView::item:selected { background: palette(Highlight) }
as the styleSheet. Maybe this helps somebody.
If you want to do it from a central qss, I guess you'll have to remove the ".tile" part from the code in the question.
.tileList::item:selected
.tile <--- remove this line
{
/*selected style*/
}
I could get this done to some extent (not a comprehensive solution), by doing following.
Make tile widget semi transparent.
Set a background color to QListWidgetItem
Set a different background color to QListWidgetItem when selected
Styles:
.titleList::item {
background-color: #fff;
}
.lstSnapQuote::item:selected {
background-color: #5555FF;
}