I want to capture image with the specific resolution.
I used this code but the image captured from camera with last resolution and the resolution of image captured does not change to size(1280, 720). I want to change the resolution before capturing the image.
imageCapture {
resolution: Qt.size(1280, 720)
onImageCaptured: {
photoPreview.source = preview
}
In many cases, the behavior of QML Camera is strange and some dependencies are not well documented(, yet).
Anyway, following code works for me:
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3
import QtQuick.Controls 1.4
import QtMultimedia 5.6
Window {
visible: true
width: 1280
height: 960
GridLayout {
id: grid
rows: 2
columns: 2
Item {
Layout.row: 0
Layout.column: 0
Layout.minimumWidth: 80
Layout.minimumHeight: 30
Button {
id: button
text: "capture"
onClicked: {
camera.stop();
camera.viewfinder.resolution = "640x480";
camera.start();
}
}
}
Camera {
id: camera
captureMode: Camera.CaptureViewfinder
viewfinder.resolution: "160x120"
imageCapture {
id: cameracapture
onImageCaptured: {
photoPreview.source = preview // Show the preview in an Image
console.log( "capture size: ", photoPreview.sourceSize );
timerHelper.restart();
}
}
onCameraStateChanged: {
console.log("camera state changed to: ", cameraState );
if ( cameraState == Camera.ActiveState && viewfinder.resolution == Qt.size(640,480) ) {
cameracapture.capture();
}
}
function cameraHelper() {
console.log( "Stopping cam..." );
camera.stop();
viewfinder.resolution = "160x120";
camera.start();
}
}
Timer {
id: timerHelper
interval: 1
onTriggered: camera.cameraHelper();
}
Item {
width: 640
height: 480
Layout.row: 1
Layout.column: 0
Layout.minimumWidth: 640
Layout.minimumHeight: 480
Image {
width: 640
height: 480
id: photoPreview
}
}
Item {
width: 640
height: 480
Layout.row: 1
Layout.column: 1
Layout.minimumWidth: 640
Layout.minimumHeight: 480
VideoOutput {
source: camera
anchors.fill: parent
focus : visible // to receive focus and capture key events when visible
}
}
}
}
If you want to switch the resolution successfully, you have to stop() and start() the Camera.
It freezes, if you try to switch the resolution back to (160,120) in onImageCaptured, so I used a Timer to obtain some kind of QueuedConnection.
In my case code:
camera.stop(); camera.viewfinder.resolution = "640x480"; camera.start();
doesn't work. When start() called i have error:
CameraBin error: "Device '/dev/video0' is busy"
CameraBin error: "Could not negotiate format"
Looks like my own app doesn't free device and i can't change resolution.
In my case the solution is to add camera.setCameraState(Camera.UnloadedState) before start() called.
Related
Is it possible to move the rectangle outside the window? The only thing I came up with is to write custom logic that will resize the top window when moving the rectangle outside the window.
Current behavior (imgur .gif):
Current behavior
Desired behavior (imgur .png):
Desired behavior
main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
Window {
id: root
width: 300
height: 500
visible: true
flags: Qt.ToolTip | Qt.FramelessWindowHint | Qt.WA_TranslucentBackground
color: "#00000000"
Rectangle {
id: draggable
color: "blue"
x: 100
y: 100
width: 100
height: 100
MouseArea {
anchors.fill: parent
property real lastMouseX: 0
property real lastMouseY: 0
onPressed: {
lastMouseX = mouseX
lastMouseY = mouseY
}
onMouseXChanged: {
draggable.x += (mouseX - lastMouseX)
}
onMouseYChanged: {
draggable.y += (mouseY - lastMouseY)
}
}
}
Rectangle {
color: "blue"
x: 100
y: 300
width: 100
height: 100
// ...
}
}
Windows can be children of other Windows. The Window behavior is still subject to certain platform-dependent behavior, but on a Desktop environment child Windows should still be able to move outside the parent Window. So simply changing your Rectangle to be a Window will give you the desired effect.
Window {
id: root
Window {
id: draggable
...
}
}
I have a program in Qt and a WebEngineView in it .I want to when my user clicked on a inputbox in webEngine a keyboard have been loaded and the inputbox get its contents from my keyboard (i wrote my own keyboard) but i can't do it .i try codes in bellow but don't work
WebEngineView {
anchors.fill:parent
id:webEng
url: "https://example.com"
visible: true
MouseArea {
id : mousearea
anchors.fill: parent
onClicked: {
mykeyboard.visible=true;
}
}
}
This is not a complete answer but this code could help:
import QtQuick 2.10
import QtWebView 1.1
import QtQuick.Controls 1.4
import QtWebEngine 1.7
Item {
width: 1280
height: 720
WebView { // or WebEngineView {
id: webview
width: 1280
height: 720
url: "http://google.com"
visible: true
onLoadingChanged: {
if (loadRequest.status === WebView.LoadSucceededStatus) {
console.log("Loaded!!")
webview.runJavaScript('
var input = document.getElementById("lst-ib");
input.addEventListener("click", function() {
alert("Clicked!");
});
'
)
}
}
}
Rectangle {
id: myDummyKeyboard
anchors.bottom: parent.bottom
width: parent.width
height: 100
color: "gray"
visible: true
border.width: 20
Button {
anchors.centerIn: parent
text: "Dummy"
onClicked: {
webview.runJavaScript('document.getElementById("lst-ib").value += "' + text + '"');
}
}
}
}
The part in the WebView (or WebEnginView) allows to display an alert when the input is clicked. But, something is missing, to link it to a QML handler. The solution is maybe to use WebChannel or maybe WebEngineScript as said by #folibis in the comments.
The part defined by myDummyKeyboard allows to add a string into the input when the user is clicking the button in the rectangle (fake keyboard).
I'd like to replace a SwipeView with an Tumbler in QML as I prefer the notion, that there is no first and no last Item.
The problem is, I can't find any other way to get this Tumbler tumble horizontally instead of vertically, but to rotate it by -90° and then rotate the Items back by +90°
This is my code so far, and works as expected:
import QtQuick 2.5
import QtQuick.Controls 2.0
import QtQuick.Window 2.2
Window {
id: root
visible: true
width: 640
height: 480
Row {
id: buttons
spacing: 2
Button {
text: '0'
onClicked: tumbl.currentIndex = 0
}
Button {
text: '1'
onClicked: tumbl.currentIndex = 1
}
Button {
text: '2'
onClicked: tumbl.currentIndex = 2
}
Button {
text: '3'
onClicked: tumbl.currentIndex = 3
}
}
Tumbler {
id: tumbl
rotation: -90 // <---- Rotate there
anchors {
top: buttons.bottom
left: buttons.left
right: buttons.right
bottom: parent.bottom
}
model: 4
delegate: Rectangle {
rotation: 90 // <---- Rotate back
color: 'red'
border.width: 15
Text {
anchors.centerIn: parent
text: index
}
}
visibleItemCount: 1
Component.onCompleted: contentItem.interactive = false
}
}
You can see the two lines, in which I do the rotation marked with a comment.
Does anybody know a way to either produce this circular behavior with a SwipeView or to change the tumble-orientation of the tumbler without this rotation trick?
I've been trying to run a BusyIndicator (http://doc.qt.io/qt-5/qml-qtquick-controls-busyindicator.html) while I am loading a qml file (http://doc.qt.io/qt-5/qml-qtquick-loader.html), but the BusyIndicator doesn't appear.
What I am trying to do is:
1- The user emits a "handlerLoader(name)", where "name" is the url of the next qml page.
2- In "onHandlerLoader" I run the busyIndicator.
3- Then, I change the Loader source.
The problem is that no matter the time I spent between steps 2 and 3, the BusyIndicator does not appear.
Moreover, when I comment step 3, the busyIndicator appears correctly.
What I am doing wrong?
Thanks!!
This is the code:
Rectangle {
visible: true
width: 800
height: 480
signal handlerLoader (string name)
Loader {
id: pageLoader;
source: "init.qml";
}
BusyIndicator {
id: busyIndicator_inicio
width: 100
height: 100
anchors.centerIn: parent
running: false
}
Connections {
target: pageLoader.item
onHandlerLoader: {
busyIndicator_inicio.running = true
pageLoader.source = name;
}
}
}
The reason is, that your heavy-loading Loader is blocking the thread.
Set it to asynchronous mode, to allow the rest of the program to run.
Further, I'd recommend to prefer declarative bindings to imperative assignments in handlers. See my example:
main.qml:
import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Controls 2.0
Window {
width: 1000
height: 800
visible: true
Button {
text: 'load'
onClicked: {
loader.source = "TestObj.qml"
}
}
Loader {
anchors.fill: parent
id: loader
active: true
asynchronous: true
visible: status == Loader.Ready
}
BusyIndicator {
id: ind
anchors.fill: parent
running: loader.status == Loader.Loading
}
}
TestObj.qml:
import QtQuick 2.0
Item {
Grid {
anchors.fill: parent
columns: width
rows: height
Repeater {
model: 100
Rectangle {
width: { for (var i = 0; i < 10000; i++) console.log(i); return 1 }
height: 1
color: 'green'
}
}
}
}
Since the asynchronous Loader might display incomplete files for some time, I set it to be visible only when its status changes to ready.
I have a trouble in changing Video item sources. In a code below I pick randomly a mov file from the folder on a mouse click. After 2 - 7 (max) times it always hangs (on changing). All movs are rather small (700 kb - 7 mb), H.264, Mac OS. Any ideas how to fix it?
import QtQuick 2.4
import QtMultimedia 5.4
import Qt.labs.folderlistmodel 2.1
Item {
id:container
property bool change_video: false
width: 320
height: 240
FolderListModel {
id: folderModel
folder: "file:///Users/michaellevin/Dropbox/Movie/Xcanvas/XXX/animation/"
nameFilters: ["*.mov"] }
Video
{ id: vvv
width: container.width
height: container.height
//autoLoad: true
autoPlay: true
anchors.fill: parent
anchors.margins: 0
onStopped: play()
}
MouseArea {
id: xxx
anchors.fill: parent
onClicked: {
var index = Math.floor(Math.random()*(folderModel.count))
print(index)
//vvv.stop()
vvv.source = folderModel.get(index, "fileURL")
//vvv.play()
}
}
Timer {
id: start; interval: 10; running: true; repeat: false;
onTriggered: vvv.source = folderModel.get(2, "fileURL")
}
}