Video plays a portion repeatedly when I implement in qml - qt

I have a video player make in qml. Slider value is binded to Mediaplayer's position as I need to show slider moving along with the video.
Also I need to move the video position to the slider position if slider is moved manually.
I wrote the below code, but i get warning and video is playing each small portion repeatedly when slide bar is moved.
warning is:
qt-reserved-files/qml/QtQuick/Controls/Slider.qml:199:5: QML RangeModel: Binding loop detected for property ""
MediaPlayer {
id: idVideo
}
Slider {
id: idSlider
anchors.bottom: idrow.top
anchors.right: parent.right
anchors.rightMargin: 85
width: 400
value: idVideo.position // for slider to move along with movie
minimumValue: 0
maximumValue: idVideo.duration
// for movie to move as slider is moved to manually.
onValueChanged: {
idVideo.seek(idSlider.value)
}
}
If I do not set onValueChanged movie will not seek as slider bar is moved. Is there a solution to this?

The issue is on android platform and I solved by below code:
onPressedChanged: {
idVideo.seek(idSlider.value)
}

Related

Qt QML Put element above a Drawer

I'm struggling with a very basic question..
Using QT 5.15.2:
We have a simple application with one main window and 2-3 sub-window (1 level down from main). The main window consists of a content item, a header and some menu-flaps distributed across the main window. So Far the sub-pages were opened with a drawer element.
However, the drawer overlays the flaps and header once opened and we need to re-instanciate the flaps and header within the drawer to have it visible. This is not really nice. Is there any way to define the z-level on which the drawer is opened? (apparently setting z doesn't work).
Item{
id: id_mainWindow
z: 0
Drawer{
id: id_subMenu1
anchors.fill: parent
z: 1
/* Not so nice workaround */
Button{
id: id_subClose
z: 100
onClicked{
id_subMenu1.close()
}
}
}
/* Unfortunately, this one gets hidden once, the drawer is open */
Button{
id: id_subOpenClose
z: 100
onClicked{
if( id_subMenu1.open ){
id_subMenu1.close()
} else {
id_subMenu1.open()
}
}
}
}
I would suggest that a Drawer is not the right component for this job as it is technically a Popup. It might be worth checking out the TabBar component instead.
Nevertheless here's a re-write of your code so that your Drawer opens without covering your id_subOpenClose button.
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Material
Rectangle {
id: id_mainWindow
anchors.fill: parent
Drawer {
id: id_subMenu1
/*
Set the Drawer's height and y position so that it does not cover your button
*/
y: id_subOpenClose.height
height: id_mainWindow.height - id_subOpenClose.height
width: id_mainWindow.width
// Do not dim background
dim: false
// Set this to zero if you want no shadow
Material.elevation: 2
edge: Qt.RightEdge
Label {
text: 'Hello World'
anchors.centerIn: parent
}
}
/*
This is your header button that was getting hidden
Here it stays as if it were part of a global header and does not get hidden by
the Drawer.
*/
Button{
id: id_subOpenClose
text: id_subMenu1.visible? 'close': 'open'
onClicked: id_subMenu1.visible? id_subMenu1.close(): id_subMenu1.open()
}
}
For an interactive WASM example of the above see here.

WebEngineView + virtual keyboard - maintain scroll position after resizing (focused input)

I have a very simple browser app based on WebEngineView and virtual keyboard made in Qt Quick.
Everything works fine - the keyboard is shown perfectly each time I click on an input in the webview, but what bothers me is that if I click on an input that is at the bottom, the keyboard covers it after opening and I cannot see what I'm typing.
I tried solving it by resizing the WebEngineView element to accomodate for the keyboard height, like most mobile apps work. It works, I can scroll the page under the keyboard but the keyboard still covers the input and I need to scroll manually.
Is there any way I could adjust the web view scroll position so the keyboard doesn't cover the focused input from QML?
I cannot do it at a single website because I allow navigation to any website user wants, so I need some universal method.
Here is my qml code:
import QtQuick 2.12
import QtQuick.Window 2.12
import FreeVirtualKeyboard 1.0
import QtWebEngine 1.8
Window {
id: appContainer;
visible: true
width: 1280
height: 600
title: qsTr("WebEngineView")
property string pathUrl: "https://www.w3schools.com/html/html_forms.asp"
WebEngineView {
id: webview
width: appContainer.width
url: appContainer.pathUrl
height: appContainer.height
}
/*
Virtual keyboard
*/
InputPanel {
id: inputPanel
z: 99
y: appContainer.height
anchors.left: parent.left
anchors.right: parent.right
states: State {
name: "visible"
when: Qt.inputMethod.visible
PropertyChanges {
target: inputPanel
y: appContainer.height - inputPanel.height
}
}
transitions: Transition {
from: ""
to: "visible"
reversible: true
ParallelAnimation {
NumberAnimation {
properties: "y"
duration: 150
easing.type: Easing.InOutQuad
}
}
onRunningChanged: {
if(!running && inputPanel.state == "visible") {
// finished showing keyboard
webview.height = appContainer.height - inputPanel.height
console.log('Keyboard shown')
} else if(running && inputPanel.state != "visible") {
// begins to hide keyboard
webview.height = appContainer.height
console.log('Keyboard starts to hide');
}
}
}
}
}
So far the resizing part works okay - I do it in onRunningChanged so the webview resizes before the transition starts and after it ends - this prevents ugly empty space showing during transition.
Update
I have achieved the effect I wanted using webview.runJavaScript together with scrollIntoView after showing the keyboard:
webview.runJavaScript("document.activeElement.scrollIntoView({block: 'nearest', inline: 'nearest', behavior: 'smooth'})");
However I'm not sure if this is solution is the best, as I don't like the fact of involving javascript evaluation into the process. I'd like to know if there's any more "native" way of doing this.
Resize WebEngineView, scroll into view
The problem with resizing the WebEngineView is that HTML will see that your device screen suddenly shrunk and may decide to present a vastly different layout, for example move menu from top to side of the screen.
Even if this has not happened, layout has changed. The position on the new "screen" does not correspond to the position on the old one, there is no 1:1 relation, which is why it scrolls to a seemingly random spot in the first place.
We can tell webpage to scroll a focused element into view of new viewport:
If it was already onscreen than nothing happens.
If not, webpage scrolls so that the element fits on the screen if possible. scrollIntoView has parameters to scroll to the top/bottom of the screen as desired
So when onscreen keyboard is opened:
Save original scrollPosition
Resize WebEngineView
Optionally assign scrollPosition to saved value - although it probably won't do you any good
Use runJavaScript to determine activeElement and make it scrollIntoView
Repeat same steps when onscreen keyboard is dismissed.
Do not resize, scroll manually
Another approach would be to not resize the "screen" and just scroll the element into view if it got covered.
This would require Qt to change VisualViewport while leaving LayoutViewport intact (see this and this for more information) but it seems that Qt cannot do that, at least not through QML alone.
That leaves us with having to do it manually: determine position with getBoundingClientRect, calculate how much space does keyboard cover, and if it is not inside our calculated uncovered view area - scrollTo it.
(you will still need runJavaScript to get inside the webpage)
Perhaps this and this SO questions can help
Other options
#Hazelnutek reported some success with document.activeElement.scrollIntoViewIfNeeded()
Please see discussion in comments to this answer below:

Showing a busy indicator or a loading image while loading large QML file

I'm working on a QML based app. where I dynamically load the content. However when running the application it takes quite a long time (5-10 secs), so I need to show any loading screen or indicator while the whole content is being loaded. Can anyone suggest me how to do it ?
For example, after I login in my application it took some time to load the next page so within that oeriod of time i want to show the loading screen.
App {
id: app
height: 400
width: 200
Rectangle {
id: rectangle
Button {
id: button
text: qsTr("GO TO NEXT PAGE")
onClicked:stackView.push("page2.qml")
}
Image {
id: image
fillMode: Image.PreserveAspectFit
source: "default-app.png"
}
}
}
Suppose this is my code then where can i use loader ? I never used it before
You can use the status from a Loader component (I'm guessing you are using that since you are loading "dynamically"). Then use that in a BusyIndicator.
Loader {
id: loader
asynchronous: true
...
BusyIndicator {
anchors.centerIn: parent
running: loader.status == Loader.Loading
}
}
Heck, the Qt docs for BusyIndicator should have get you going!

How to remove bounds of the Flickable QML component?

I want to display a large amount of content, for example, a grid of multiple images inside a window that is smaller than the content, similar to a geographical map but instead of a map, I want my own components as the "map". For this minimal working example, let's take for the content a grid of images with a total size of 1000x1000 with a window into this content of only 300x300.
I have tried 2 different approaches, but I will only go into detail of the first approach as that is the one that got me closest to my desired result:
I have tried the Flickable component but the content cannot be moved outside the predefined bounds, making the user unable to move the view in order to display all the parts of the content. So the simplest solution that I'm thinking about now is if I could remove these bounds from the Flickable component, but how?
I have also tried the Map component but it requires a "plugin" and I was unable to figure out how to use this component with my own content of an image grid.
The content that I want to show is something this
Grid {
columns: 5
spacing: 2
Repeater {
model: ListModel {
ListElement {
path: 'test1'
}
ListElement {
path: 'test2'
}
// ...
ListElement {
path: 'test25'
}
}
Rectangle {
width: 200
height: 200
Image {
anchors.fill: parent
source: 'file:' + path
}
}
}
}
I tried, putting this inside the Flickable like this
Flickable {
anchors.centerIn: parent
width: 300
height: 300
contentWidth: 1000
contentHeight: 1000
clip: true
// INSERT CUSTOM GRID COMPONENT HERE
}
This results in a 300x300 view inside the content as expected, but once you start to flick through the content to view different parts of it, you are stopped by the bounds preventing you from seeing anything outside these bounds. You can see it while dragging but once you release the view of the content is reset to these bounds.
So how do I remove these bounds? (Or is there a different component more suitable for my application?)
Here is a gif that shows how the content can be dragged passed the bounds, but once released it will only go up to the bounds and not further
I found the issue, I set the contentWidth and contentHeight of the Flickable incorrectly, this example works fine. The contentWidth and contentHeight determine the bounds in which you can flick.

Connect a slider to control zoom on qml Camera

I am using Camera to take movies.
I want to use a slider to zooming video like zoom of google map.
I've found another Question on SO but the proposed solution works for click whereas I would like to develop a solution for slider.
I wrote code that is not working correctly.
I have not found error, but video size will be very large, then I do not see video.
I try to set digitalZoom for camera but I have this error:
The camera doesn't support zooming. .I know my camera does not support "DigitalZoom" and "OpticalZoom". I want to find a way to zoom in on video taken from camera.
My camera is dino ccd.
Excuse me friends, I can not add comment, I have this error: "You must have 50 reputation to comment".
VideoOutput {
id: viewfinder
source: camera
anchors.fill: parent
focus : true
transform: [
Scale {
id: zoomScale
},
Translate {
id: zoomTranslate
}
]
//Keys.onLeftPressed: viewfinder.seek(viewfinder.position - 5000)
//Keys.onRightPressed: viewfinder.seek(viewfinder.position + 5000)
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.AllButtons
onClicked: {
var zoomIn = mouse.button === Qt.LeftButton;
zoomScale.origin.x = mouse.x;
zoomScale.origin.y = mouse.y;
}
}
Slider {
id:zoomVideo
orientation: Qt.Vertical
minimumValue: 0
maximumValue: 100
stepSize: 10
onValueChanged: {
zoomScale.xScale = zoomVideo.value
zoomScale.yScale = zoomVideo.value
}
}
}
Are you trying to implement a zoom-in/zoom-out functionality using slider just like a normal mobile camera app does, if yes then consider the below untested code snippet because currently I don't have a machine with Qt IDE installed, but it should help you to understand the concept.
Camera {
id: camera
digitalZoom:zoomSlider.value
//if opticalZoom is supported uncomment below line
//opticalZoom:zoomSlider.value
// rest of your settings
}
VideoOutput {
id: viewfinder
source: camera
anchors.fill: parent
focus : true
}
Slider {
id:zoomSlider
orientation: Qt.Vertical
minimumValue: 0
maximumValue: camera.maximumDigitalZoom //or camera.maximumOpticalZoom
stepSize:camera.maximumDigitalZoom/10 // going through 10 steps
value:1.0 // initial zoom level
anchors{
left:parent.left
leftMargin:5
verticalCenter:parent.verticalCenter
}
}
and also I would like you to have a look at the official documentation for these types.Slider, Camera . If you need further clarifications post comments below.

Resources