Framing VideoOutput item in Qt QML - qt

I am using a VideoOutput item, which I have placed inside a Rectangle. This VideoOutput goes on top of the Rectangle, of its border and its rounded corners.
Rectangle{
radius: 12
width: 200
height: width
border.color: black
border.width: 15
VideoOutput {
fillMode: VideoOutput.PreserveAspectCrop
anchors.fill: parent
source: myCamera
autoOrientation: true
}
}
Camera {
id: myCamera
focus {
focusMode: CameraFocus.FocusContinuous
focusPointMode: CameraFocus.FocusPointAuto
}
captureMode: Camera.CaptureViewfinder
}
I intentionaly made the border thick so it really shows what is going on. The border is hidden by the VideoOutput, and the rounded corners are ignored.
I can imagine that the VideoOutput item would use some acceleration tricks, so it might not play well with standard QML item behaviour. But is there a way get this to work, without adding a filter element, or is this the expected behaviour?

Related

QML animations and effects

imagine that we have arrow image as here:
but we want to make from this image an animation:
question
This not very elegant animation was created from a set of different arrow images.
But i want to make same animation by qml. Do you know any components(preferably qml but if you do not know, you can advise me qt classes) with which help i can reach that?
And another question, does it make sense from the point of view of performance to search any ways to reach that instead of combine set of images to gif-format?
Updating based on new information that the arrow has a background.
You need to crop out the arrow to an image file with a transparent background and have the background as a separate image.
From there, you can use a similar concept as below, but with the arrow growing. I believe you will be able to find an image mode that fits the image vertically and does not manipulate it horizontally. I would start by trying fillMode: Image.TileHorizontally.
Treat this as pseudo code, I don't have access to a computer to run this on at the moment.
Image
{
id: backgroundImage
source: "background.png"
Image
{
id: arrowWithTransparentBackground
fillMode: Image.TileHorizontally
source: "arrow.png"
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
SequentialAnimation on width {
loops: Animation.Infinite
PropertyAnimation { from 0: to: parent.width }
}
}
}
Old answer for reference, before knowing there was a background to the image:
QML very nicely animates size changes. You could easily have a rectangle on top of your image anchored to the left side that is white and grows from 0 to arrow.width.
Treat this as pseudo code, I don't have access to a computer to run this on at the moment.
Image
{
id: arrowImage
source: "arrow.png"
Rectangle
{
color: "white"
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
SequentialAnimation on width {
loops: Animation.Infinite
PropertyAnimation { from 0: to: parent.width }
}
}
}

Culling items that are outside the visible area

From the docs:
The default renderer does not do any CPU-side viewport clipping nor occlusion detection. If something is not supposed to be visible, it should not be shown. Use Item::visible: false for items that should not be drawn. The primary reason for not adding such logic is that it adds additional cost which would also hurt applications that took care in behaving well.
So is there a trick to do it easily, without implementing it myself?
Note that in my case the items that are outside the visible area are there because they are in a ScrollView and they are not scrolled-to.
The reason I want culling is to reduce CPU usage for full-scene redraws.
Here is a trivial example you can extend upon:
Window {
visible: true
width: 640
height: 480
Rectangle {
anchors.centerIn: parent
width: 200
height: 200
color: "yellow"
Flickable {
id: view
anchors.fill: parent
contentWidth: 200
contentHeight: col.height
property real span : contentY + height
Column {
id: col
x: 90
spacing: 2
Repeater {
model: 50
delegate: Rectangle {
width: 10
height: 10
color: inView ? "blue" : "red"
property bool inView: y > view.contentY && y < view.span
}
}
}
}
}
}
Obviously, a full-proof solution would also include the item's height in the calculation. You can also do the check in the x axis if necessary.
To add to dtech's answer, I just learned that there are QML components, such as GridView and ListView, that do culling automatically.

Building TabBar in QML - Loader doesn't show all the Rectangles

import QtQuick 2.4
import QtQuick.Window 2.2
Window
{
visible: true
height: 500
width: 500
property VisualItemModel contentToBeShownOnTabClick : visualItemModelDemo
property variant tabLabels : ["Navigation", "Payload", "System Control"]
VisualItemModel
{
id: visualItemModelDemo
Rectangle
{
id: navigationTab
color: "green"
height: 200
width: 200
}
Rectangle
{
id: navigationTab1
color: "darkgreen"
height: 200
width: 200
}
Rectangle
{
id: navigationTab2
color: "lightgreen"
height: 200
width: 200
}
}
MainForm
{
Component
{
id: tabsOnBottomComponent
Repeater
{
model: tabLabels
// The Tabs
Rectangle
{
id: tabsOnBottom
// This anchoring places the tabs on the outer top of the parent rectangle.
anchors.top: parent.bottom
anchors.topMargin: 180
color: "lightsteelblue"
border.color: "steelblue"
border.width: 2
implicitWidth: Math.max ((labelTabsBottom.width + 4), 80)
implicitHeight: 20
radius: 2
// Tabs Text/Label
Text
{
id: labelTabsBottom
anchors.centerIn: parent
color: "white"
rotation: 0
// With reference to mode: tabLabels
text: modelData
font.pointSize: 11
}
MouseArea
{
anchors.fill: parent
onClicked: bottomTabClicked (index);
}
}
}
}
Rectangle
{
// The things which get displayed on clicking of a tab will be shown in this rectangle.
id: areaForTabContents
border.color: "black"
border.width: 10
height: parent.height
width : parent.width
color : "pink"
// These are the tabs displayed in one row - horizontally.
Row
{
id: horizontalTabs
Loader
{
anchors.fill: parent
sourceComponent: tabsOnBottomComponent
}
}
}
anchors.fill: parent
}
}
This gets shown as follows:
whereas I want it to see 3 rectangles there side by side.
Loader is not a transparent type w.r.t. the containing type, Row in this case. I think this is an issue related to creation context and the way Repeater works. From the documentation of the latter:
Items instantiated by the Repeater are inserted, in order, as children of the Repeater's parent. The insertion starts immediately after the Repeater's position in its parent stacking list. This allows a Repeater to be used inside a layout.
The Rectangles are indeed added to the parent which is the Loader, they stack up - Loader does not provide a positioning policy - then they are added to the Row resulting in just one Item (the last one) to be visible.
You can tackle the problem with few different approaches, depending on the properties you want to maintain or not. I would get rid of anchoring in the Component and move it to the containing Row. A too specific anchoring inside a Component could be a pain in the neck when it is instanced and used all over a (not so small) project.
As a first approach you can re-parent the Repeater to the Row, i.e. you can rewrite code as:
Row
{
id: horizontalTabs
Loader
{
sourceComponent: tabsOnBottomComponent
onLoaded: item.parent = horizontalTabs
}
}
However this would result in warnings due to the Component anchoring references not working as expected any more.
If you still want to maintain the anchoring, as defined in the Component, and off-load the creation, you can go for the dynamic way (if the semantics fits in your use case), i.e. you can use createObject. This way you totally avoid the Loader and the related issue. For instance, you can create the Repeater once the Row has completed its creation:
Row
{
id: horizontalTabs
Component.onCompleted: tabsOnBottomComponent.createObject(horizontalTabs)
}
Clearly, the creation code can be move anywhere else, depending on your needs.

Overlapping mouseareas in QtQuick 2.0

I have list of items in QML 2.0 and I want to display item's context menu (red box in the picture) only when mouse is inside black mouseArea. Context menu contains a few buttons, each of them has own museArea. In QtQuick 1.0 it works as expected, but in 2.0 not. When I move the cursor between small red boxed (context menu's items), black MouseArea::onExited is called (and context menu isn't shown). It looks like small red mouseareas covered the larger, black mousearea. If I set:
z: 10
in black mouseArea, onExited isn't called when cursor is above small red boxes, but I can't use small mouseares hovering effects. What should I do to have an access to small red boxes' mouseareas and simultanously not calling black mouseArea::onExited when cursor is above red box?
Instead of relying on the mouseArea onExited and onEntered events, you could enable hovering and check the containsMouse property. Here's a working example (QtQuick 2.0):
Column
{
spacing: 10
Repeater
{
model:4
Rectangle
{
height: 100
width: parent.width
border.color: "black"
MouseArea
{
id: mouseArea
anchors.fill: parent
hoverEnabled: true
}
Rectangle
{
visible: mouseArea.containsMouse
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.margins: 20
width: 200
border.color: "red"
Rectangle
{
anchors.centerIn: parent
color: "purple"
width: 20
height: 20
MouseArea
{
anchors.fill: parent
onClicked: print("clicked")
}
}
}
}
}
}
If a MouseArea overlaps with the area of other MouseArea items,
you can choose to propagate clicked, doubleClicked and
pressAndHold events to these other items by setting
propagateComposedEvents to true and rejecting events that should
be propagated. See the propagateComposedEvents documentation for
details.
Source

QML MouseArea onEntered hoverEnabled does not work

a pretty simple scenario, actually:
Text {
text: "Hover me!"
font.family: "Arial"
font.pointSize: 16
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: {
parent.color = "#ffffff"
}
onExited: {
parent.color = "#000000"
}
}
}
As you can see, all i want is that the text color changes when i hover it. However, it works only when i'm holding down my left mouse button. Since i'm pretty new to Qt, i've no idea where the problem could be. I googled all day to find an answer, but everything leads me to the "set hoverEnabled: true" solution, which i'm already using.
I'm working on windows with Qt 2.4.1 including VPlay (doesn't think that VPlay matters here)
From your snippet, it looks like you're not assigning the Text element a size (either explicitly or via anchoring), so it has a width/height of (0,0), which means it will never contain the mouse cursor. Note that in QtQuick, the size of items is not defined by their contents or where they paint (an item can paint anywhere outside of its (position, size) rectangle). An item without explicit width/height attributes or anchoring will have a size of (0,0), no matter how it appears on screen.
In the following example, the mouse area has a size of 360, 360 inherited from its parent rectangle (via anchors.fill: parent):
import QtQuick 2.0
Rectangle {
width: 360
height: 360
color: "black"
Text {
anchors.centerIn: parent
text: qsTr("Hello World")
color: mouseArea.containsMouse ? "red" : "white"
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
}
}
}
I preferred the declarative approach using a property binding with containsMouse here, but onEntered/onExited would work as well.

Resources