Custom Component in qml - qt

I am Using custom inputRow and MenuButton is placed Outside component when i try to print value of Val1 and Val2 it gives "ReferenceError: val1 is not defined",
how can i access it Outside component.
InputRow {
name:"Command"
enabled: true
filename: "qrc:/AutonomyPlatform/Images/Parameters.svg"
component: Column {
spacing: 10
Row{
spacing: 50
Text {
text: "Val1"
color: Colors.menuBodyTextNormal
font.pointSize: 10
}
TextInput {
id:val1
width: 5
text: selectedModel ? "0" : ""
font.pointSize: 10
color: Colors.menuBodyTextInput
}
Text {
text: "m"
color: Colors.menuBodyTextNormal
font.pointSize: 10
}
}
Row {
spacing: 50
Text{
text: "Val2"
color: Colors.menuBodyTextNormal
font.pointSize: 10
}
TextInput {
id:val2
width: 5
text: selectedModel ? "0" : ""
font.pointSize: 10
color: Colors.menuBodyTextInput
}
Text {
text: "m"
color: Colors.menuBodyTextNormal
font.pointSize: 10
}
}
} //End of Column
MenuButton {
label: "Send"
buttonHeight: 25
buttonWidth: 35
onMenuButtonClicked:
{
console.log("VAL1",val1.text) //ReferenceError: val1 is not defined,
console.log("VAL2",val2.text)
console.log("SEND")
}
}
}
When i put Menubutton inside column component it prints as expected but when its outside component i get ReferenceError as mentioned above

As I mentioned above that could be done in a declarative style:
For example:
Window {
id: window
visible: true
width: 400
height: 600
title: qsTr("Test")
property string str1: ""
property string str2: ""
onStr1Changed: printOut();
onStr2Changed: printOut();
function printOut()
{
console.log(str1, str2);
}
ColumnLayout {
anchors.centerIn: parent
Loader {
id: loader1
sourceComponent: TextInput {
id: txt1
text: "xxx"
Binding {
target: window
property: "str1"
value: txt1.text
}
}
}
Loader {
id: loader2
sourceComponent: TextInput {
id: txt2
text: "xxx"
Binding {
target: window
property: "str2"
value: txt2.text
}
}
}
}
Component.onCompleted: {
loader1.active = true;
loader2.active = true;
}
}

Got a way to access this :
InputRow{
id: userForm
property var userInput1
property var userInput2
component :
Column{
...
TextInput {
id:val1
text: "777"
onTextChanged: userForm.userInput1 = text
Component.onCompleted : userForm.userInput1 = text
}
}
MenuButton{
onClicked : console.log(userForm.userInput1)
}

Related

How to use Qt MediaDevices type to switch AudioOutput device

I think I'm missing something here, but I can't figure out how to set a AudioOutput device from MediaDevices audioOutputs list with the QML Components
audioOutput: AudioOutput {
id: playerOutput
device: mediaDevices.defaultAudioOutput
onDeviceChanged: {
console.log("Output device changed " + device)
}
Component.onCompleted: {
console.log(mediaDevices.audioOutputs)
}
}
MediaDevices {
id: mediaDevices
}
The 2 devices are showing:
QAudioDevice(2, Built in earpiece (IN2023), false, Output),
QAudioDevice(3, Built in speaker (IN2023), false, Output)
but I don't understand how to change it, I've tried playerOutput.setDevice() description and id but it wants a QAudioDevice (it only provides description, id and mode, the documentation for both is very vague:
This property can be used to select an output device from the
QtMultimedia::MediaDevices::audioOutputs() list.
https://doc.qt.io/qt-6/qml-qtmultimedia-mediadevices.html
https://doc.qt.io/qt-6/qml-qtmultimedia-audiooutput.html#device-prop
Any help would be appreciated!
Thanks
You can assign an object from mediaDevices.audioOutputs to the devices property of your AudioOutput.
playerOutput.device = mediaDevices.audioOutputs[index]
where index is a valid index in the audioOutputs list.
import QtQuick
import QtQuick.Window
import QtMultimedia
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello AudioOutput")
MediaDevices {
id: mediaDevices
}
MediaPlayer {
id: mediaPlayer
source: "qrc:/Test_ogg_mp3_48kbps.wav"
audioOutput: AudioOutput {
id: playerOutput
device: mediaDevices.defaultAudioOutput
onDeviceChanged: { console.log("Output device changed " + device) }
Component.onCompleted: { console.log(mediaDevices.audioOutputs) }
}
}
component MediaPlayerButton : Rectangle {
id: button
property alias text: label.text
property bool active: false
signal clicked
width: 100; height: 40; radius: 10
color: button.active ? "tomato" : "ghostwhite"
border.color: "gainsboro"
border.width: buttonMouseArea.containsMouse ? 4 : 2
Text {
id: label
anchors.centerIn: parent
font.pointSize: 18
}
MouseArea {
id: buttonMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: button.clicked()
}
}
Column {
spacing: 10
anchors.centerIn: parent
Row {
spacing: 10
MediaPlayerButton {
text: qsTr("Play")
active: mediaPlayer.playbackState === MediaPlayer.PlayingState
onClicked: { mediaPlayer.play() }
}
MediaPlayerButton {
text: qsTr("Pause")
active: mediaPlayer.playbackState === MediaPlayer.PausedState
onClicked: { mediaPlayer.pause() }
}
MediaPlayerButton {
text: qsTr("Stop")
active: mediaPlayer.playbackState === MediaPlayer.StoppedState
onClicked: { mediaPlayer.stop() }
}
}
Repeater {
model: mediaDevices.audioOutputs
Row {
spacing: 10
Rectangle {
id: r
width: 40; height: 40; radius: 20
color: mediaPlayer.audioOutput.device === mediaDevices.audioOutputs[index] ? "tomato" : "ghostwhite"
border.color: "gainsboro"
border.width: jackMouseArea.containsMouse ? 4 : 1
MouseArea {
id: jackMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: playerOutput.device = mediaDevices.audioOutputs[index]
}
}
Text {
anchors.verticalCenter: r.verticalCenter
font.pointSize: 12
text: mediaDevices.audioOutputs[index].description
}
}
}
}
}

QML, failed by using components of another qml file

I have a problem with the usage qml components from another qml file. I have 2 files, main.qml and menu.qml (menu.qml is in another folder called menu). In the menu.qml I have my menu, which I want to use in main.qml
import QtQuick 2.9
import QtQuick.Controls 2.4
Menu {
id: routingMenu
width: maximumWidth
height: 200
y: 20
cascade: true
Rectangle {
Label {
x: (app_window.width / 8)
text: "FROM:"
font.pixelSize: 22
font.italic: true
color: "black"
}
Label {
y: routingMenu.height / 7
text: "Country:"
font.pixelSize: 22
font.italic: true
color: "black"
}
Label {
y: routingMenu.height / 2.5
text: "City:"
font.pixelSize: 22
font.italic: true
color: "black"
}
Label {
y: routingMenu.height / 1.6
text: "Street:"
font.pixelSize: 22
font.italic: true
color: "black"
}
Label {
y: routingMenu.height / 1.2
text: "Postal Code:"
font.pixelSize: 22
font.italic: true
color: "black"
}
} //Rectangle
Rectangle {
x: app_window.width / 2
Label {
x: (app_window.width / 4)
text: "TO:"
font.pixelSize: 22
font.italic: true
color: "black"
}
Label {
y: routingMenu.height / 7
text: "Country:"
font.pixelSize: 22
font.italic: true
color: "black"
}
Label {
y: routingMenu.height / 2.5
text: "City:"
font.pixelSize: 22
font.italic: true
color: "black"
}
Label {
y: routingMenu.height / 1.6
text: "Street:"
font.pixelSize: 22
font.italic: true
color: "black"
}
Label {
y: routingMenu.height / 1.2
text: "Postal Code:"
font.pixelSize: 22
font.italic: true
color: "black"
}
} //Rectangle
Button {
id: sendDataToItem
width: 100
height: 40
x: app_window.width / 2.7
text: "Send"
onClicked: {
//fromAddress.country: "";
//fromAddress.city: "";
//fromAddress.street: "";
//fromAddress.postalCode: "";
//toAddress.country: "";
//toAddress.city: "";
//toAddress.street: "";
//toAddress.postalCode: "";
}
} //sendDataToItem
} //Menu
I tried to use a Component, but it didn't helped me. That is code of my main.qml
import QtQuick 2.10
import QtQuick.Controls 2.2
import QtQuick.Window 2.0
import QtLocation 5.6
import QtPositioning 5.6
import "menu"
ApplicationWindow {
id: app_window
visible: true
width: maximumWidth
height: maximumHeight
title: qsTr("Navigation")
PositionSource {
active: true
onPositionChanged: {
//map_id.center = position.coordinate;
}
}
Plugin {
id: mapPlugin_
name: "osm"
}
/*Loader {
id: loadered
focus: true
source: "menu/menu.qml"
active: true
}*/
Rectangle {
id: mapRectangleID
width: 800
height: 800
x:0
y:20
Map {
id: map_
anchors.fill: parent
plugin: mapPlugin_
center: QtPositioning.coordinate(51.320729390711975,12.280097007751465)
zoomLevel: 15
MapQuickItem {
id: marker_id
coordinate: QtPositioning.coordinate(59.91, 10.75)
sourceItem: Image {
id: endPointImage
source: "assets/marker.png"
width: 100
height: 100
} //size and position of maker
anchorPoint.x: endPointImage.width / 2
anchorPoint.y: endPointImage.height
} //marker
RouteModel {
id: routeBetweenPoints
plugin: Plugin { name: "osm" }
query: RouteQuery {id: routeQuery }
Component.onCompleted: {
routeQuery.addWaypoint(QtPositioning.coordinate(51.318784,12.2773504 ));
routeQuery.addWaypoint(QtPositioning.coordinate(51.3117764,12.280909000000065 ));
//routeQuery.addWaypoint(endPointGeaocodeModel)
update();
}
} //start and end point
MapItemView {
model: routeBetweenPoints
delegate: Component {
MapRoute {
route: routeData
line.color: "red"
line.width: 10
}
} //Component
}//linie, die beide punkte verbindet
GeocodeModel{
id: endPointGeaocodeModel
plugin: Plugin { name: "osm" }
query: "Sandakerveien 116, Oslo"
onLocationsChanged: {
if (count> 0){
marker_id.coordinate = get(0).coordinate
map_id.center = get(0).coordinate
}
}
Component.onCompleted: update()
} //suche den platz mit strasse und stadt
//! [geocode0]
Address {
id: fromAddress
city: ""
country: ""
street: ""
postalCode: ""
} //fromAddress
//! [geocode0]
Address {
id: toAddress
country: ""
city: ""
street: ""
postalCode: ""
} //toAddress
} //Map
} //mapRectangleID
Button {
id: btn_close
width: 100
height: 20
text: "Close"
onClicked: {
Qt.quit();
}
}
Button {
id: btn_routing
width: 100
height: 20
x:100
text: "Routing"
onClicked: {
routingMenu.open();
}
}
Button {
id: btn_oldWay
width: 100
height: 20
x:200
text: "Old way"
onClicked: {
oldWayMenu.open();
}
}
Button {
id: rest
width: parent.width - x
height: 20
x:300
text: ""
onClicked: {
}
}
} //ApplicationWindow
I tried 2 ways to resolve the problem. One with the Loader, but I can't open my menu, and the another with example of QT which is in MapViewer Example. They import only the order and use the id of the component. But it doesn't work. I think, I do something wrong in my code, can someone tell me what I'm doing wrong or show me the right way to resolve my problem.
I think that the most important part of the code is:
Loader {
id: loadered
focus: true
source: "menu/menu.qml"
active: true
}
And then, how I'm using it:
Button {
id: btn_routing
width: 100
height: 20
x:100
text: "Routing"
onClicked: {
routingMenu.open();
}
}
By the button I'm using the component name, because I imported menu. But if I want to use the loader, I would set the visible in loader as false and then set onClicked as true. But I tried this and it didn't work.
Thanks for help
DC
The id is only valid within the .qml outside it has no meaning, for example let's say you're going to create 4 menus then if you would use the id routingMenu, which of the menus would you refer to? because that would cause confusion. So if you want to use the item loaded by Loader you must do it using the item property.
Loader {
id: loadered
focus: true
source: "menu/menu.qml"
active: true
}
// ...
Button {
id: btn_routing
width: 100
height: 20
x:100
text: "Routing"
onClicked: loadered.item.open()
}

qml: Rectangle animation not working

I have an application, where I want to apply an animation to a button/ rectangle and after this executes the animation, it should display a dialog. The problem is that when the dialog.visible: true is called on onClicked, the animation is not executed. I have created a test application here are the two qml files:
main.qml
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
visible: true
FileDialogs
{
id:fileDialog
visible:false
width:800
height:800
//modality: Qt.WindowModal
z:10
}
Rectangle
{
id:rect
width:200
height:200
color:"blue"
Text
{
id:simpleText
text:"This is a button"
font.pixelSize: 20
color:"white"
width:200
height:200
}
states: [
State {
name: "PRESSED"
},
State {
name: "RELEASED"
}
]
transitions: [
Transition {
from: "PRESSED"
to: "RELEASED"
PropertyAnimation { id: selectAnim; target: rect; properties: "scale"; easing.type: Easing.OutBack; easing.amplitude: 3.0; easing.period: 1.5; from: 0; to: 1; duration: 400 }
}
]
MouseArea {
anchors.fill: parent
onPressed:
{
parent.state = "PRESSED"
}
onReleased:
{
parent.state = "RELEASED"
}
onClicked: {
fileDialog.visible=true;
}
}
}
}
FileDialogs.qml, from Qt examples
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.1
import QtQuick.Layouts 1.1
import QtQuick.Window 2.0
Item {
width: 580
height: 400
SystemPalette { id: palette }
clip: true
//! [filedialog]
FileDialog {
id: fileDialog
visible: fileDialogVisible.checked
modality: Qt.WindowModal
title: fileDialogSelectFolder.checked ? "Choose a folder" :
(fileDialogSelectMultiple.checked ? "Choose some files" : "Choose a file")
selectExisting: fileDialogSelectExisting.checked
selectMultiple: fileDialogSelectMultiple.checked
selectFolder: fileDialogSelectFolder.checked
nameFilters: [ "Image files (*.png *.jpg)", "All files (*)" ]
selectedNameFilter: "All files (*)"
sidebarVisible: fileDialogSidebarVisible.checked
onAccepted: {
console.log("Accepted: " + fileUrls)
if (fileDialogOpenFiles.checked)
for (var i = 0; i < fileUrls.length; ++i)
Qt.openUrlExternally(fileUrls[i])
}
onRejected: { console.log("Rejected") }
}
//! [filedialog]
ScrollView {
id: scrollView
anchors {
left: parent.left
right: parent.right
top: parent.top
bottom: bottomBar.top
leftMargin: 12
}
ColumnLayout {
spacing: 8
Item { Layout.preferredHeight: 4 } // padding
Label {
font.bold: true
text: "File dialog properties:"
}
CheckBox {
id: fileDialogModal
text: "Modal"
checked: true
Binding on checked { value: fileDialog.modality != Qt.NonModal }
}
CheckBox {
id: fileDialogSelectFolder
text: "Select Folder"
Binding on checked { value: fileDialog.selectFolder }
}
CheckBox {
id: fileDialogSelectExisting
text: "Select Existing Files"
checked: true
Binding on checked { value: fileDialog.selectExisting }
}
CheckBox {
id: fileDialogSelectMultiple
text: "Select Multiple Files"
Binding on checked { value: fileDialog.selectMultiple }
}
CheckBox {
id: fileDialogOpenFiles
text: "Open Files After Accepting"
}
CheckBox {
id: fileDialogSidebarVisible
text: "Show Sidebar"
checked: fileDialog.sidebarVisible
Binding on checked { value: fileDialog.sidebarVisible }
}
CheckBox {
id: fileDialogVisible
text: "Visible"
Binding on checked { value: fileDialog.visible }
}
Label {
text: "<b>current view folder:</b> " + fileDialog.folder
}
Label {
text: "<b>name filters:</b> {" + fileDialog.nameFilters + "}"
}
Label {
text: "<b>current filter:</b>" + fileDialog.selectedNameFilter
}
Label {
text: "<b>chosen files:</b> " + fileDialog.fileUrls
}
Label {
text: "<b>chosen single path:</b> " + fileDialog.fileUrl
}
}
}
Rectangle {
id: bottomBar
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
height: buttonRow.height * 1.2
color: Qt.darker(palette.window, 1.1)
border.color: Qt.darker(palette.window, 1.3)
Row {
id: buttonRow
spacing: 6
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 12
height: implicitHeight
width: parent.width
Button {
text: "Open"
anchors.verticalCenter: parent.verticalCenter
onClicked: fileDialog.open()
}
Button {
text: "Pictures"
tooltip: "go to my Pictures directory"
anchors.verticalCenter: parent.verticalCenter
enabled: fileDialog.shortcuts.hasOwnProperty("pictures")
onClicked: fileDialog.folder = fileDialog.shortcuts.pictures
}
Button {
text: "Home"
tooltip: "go to my home directory"
anchors.verticalCenter: parent.verticalCenter
enabled: fileDialog.shortcuts.hasOwnProperty("home")
onClicked: fileDialog.folder = fileDialog.shortcuts.home
}
}
}
}
The animation is happening. It's just the FileDialog is covering the button before you can see it animate. Release the mouse click outside the button area and you'll see the animation (this way onClicked is not triggered).
A way to show the dialog after the animation:
states: [
State {
name: "PRESSED"
},
State {
name: "RELEASED"
}
]
transitions: [
Transition {
from: "PRESSED"
to: "RELEASED"
PropertyAnimation { id: selectAnim; target: rect; properties: "scale"; easing.type: Easing.OutBack; easing.amplitude: 3.0; easing.period: 1.5; from: 0; to: 1; duration: 400 }
onRunningChanged: {
if (!running) {
fileDialog.visible = true
}
}
}
]
MouseArea {
anchors.fill: parent
onPressed:
{
parent.state = "PRESSED"
}
onClicked: {
parent.state = "RELEASED"
}
}

How to add a editable TableView header in qml?

import QtQuick 2.7
import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3
Rectangle {
width: 640
height: 480
ListModel {
id: tstModel
ListElement { animal: "dog" }
}
TableView {
id: tableView
anchors.fill: parent
model: tstModel
headerDelegate: Item{
height: 50
width: animalColumn.width
TextField{
text: styleData.value
anchors.fill: parent
}
}
TableViewColumn {
id: animalColumn
title: "Animal"
role: "animal"
width: 50
resizable: false
movable: false
}
}
}
This code is not acting as I expect. Textfield gets focus only when I am clicking the header with right button. And there is a Textfield works fine next to the first column header, but it's not what I want.
How to add a editable TableView header in qml?
I find this headerDelegate to be rather buggy or not supposed to be used in this scenario. I would rather implemnt a header from scrath to use for your use-case. Try this as a starting point:
Rectangle {
width: 640
height: 480
ListModel {
id: tstModel
ListElement { animal: "cat" }
ListElement { animal: "cat" }
ListElement { animal: "cat" }
ListElement { animal: "cat" }
ListElement { animal: "cat" }
ListElement { animal: "cat" }
ListElement { animal: "cat" }
}
TextField{
id: tableViewCustomHeader
property int curRow: tableView.currentRow
property bool isActual: curRow >= 0
function reloadText() { text = tstModel.get(curRow).animal }
function saveText() { tstModel.setProperty(curRow, "animal", text); tableView.model = tstModel; }
width: animalColumn.width
height: isActual ? 20 : 0
onCurRowChanged: {
if ( isActual >= 0 ) reloadText();
focus = true;
}
onTextChanged: if ( isActual >= 0 ) saveText()
}
TableView {
id: tableView
anchors {
top: tableViewCustomHeader.bottom
bottom: parent.bottom
left: parent.left
right: parent.right
}
model: tstModel
headerVisible: false
TableViewColumn {
id: animalColumn
title: "Animal"
role: "animal"
width: 200
resizable: false
movable: false
}
}
}
You can edit this anyway you want afterwards.
If it's a strict requirement to go with headerDelegate - this what I've end up with:
Rectangle {
width: 640
height: 480
ListModel {
id: tstModel
ListElement { animal: "dog" }
ListElement { animal: "cat" }
}
TableView {
id: tableView
anchors.fill: parent
model: tstModel
headerDelegate:
TextField{
property int curRow: tableView.currentRow
function reloadText() { text = tstModel.get(curRow).animal }
function saveText() { tstModel.setProperty(curRow, "animal", text); tableView.model = tstModel; }
onCurRowChanged: {
if ( curRow >= 0 ) reloadText()
}
onTextChanged: saveText()
width: parent.width
}
TableViewColumn {
id: animalColumn
title: "Animal"
role: "animal"
width: 200
resizable: false
movable: false
}
}
}
But, again, it works in a very strange way once you are adding TextField to it, so I would vote against it.

Is there easy way to duplicate a RowLayout in QtQuick?

In my ui.qml I have:
RowLayout {
id: rowLayout2
x: 0
y: 397
width: 640
height: 50
clip: false
Text {
id: text4
width: 105
height: 32
text: qsTr("房间类型")
font.pixelSize: 17
wrapMode: Text.WordWrap
}
ComboBox {
id: comboBox1
activeFocusOnPress: false
model: ListModel {
id: cbItems
ListElement { text: "标准间"; color: "Yellow" }
ListElement { text: "三人间"; color: "Green" }
ListElement { text: "大床房"; color: "Brown" }
ListElement { text: "豪华套房"; color: "Blue" }
}
}
}
And I want to make a button that when clicked on duplicates this RowLayout below the original one, how do I do that?
Put it inside a Repeater and increment the model count when the button is clicked.
Button {
onClicked: {
repeater.model += 1;
}
}
...
Column {
Repeater {
model: 1
// Your rowLayout2 code
}
}

Resources