Using Loader object in a Layout QML - qt

I want to use a loader object in a ColumnLayout object in this form:
Item{
width: 500
height: 300
focus: true
Keys.onLeftPressed: state = "matrix"
ColumnLayout{
id: panel
anchors.fill: parent
RowLayout{
Layout.minimumHeight: 30
Text {
Layout.fillWidth: true
text: "some"
}
Slider{
Layout.fillWidth: true
}
Button {
text: "otro"
}
}
Loader {
id: load
Layout.fillWidth: true
height: 30
width: 30
}
}
states: [
State {
name: "matrix"
PropertyChanges {
target: load
sourceComponent: tab
}
}
]
Component {
id:tab
Rectangle {
color: "red"
height: 30
width: 30
}
}
}
I use a key event for change the state property, but "tab" component don't load in the root item.
Can any one help me fix this problem?

A Loader cannot have the layout.fillWidth. It must be set when the component load :
Item{
width: 500
height: 300
focus: true
Keys.onLeftPressed: state = "matrix"
ColumnLayout{
id: panel
anchors.fill: parent
RowLayout{
Layout.minimumHeight: 30
Text {
Layout.fillWidth: true
text: "some"
}
Slider{
Layout.fillWidth: true
}
Button {
text: "otro"
}
}
Loader { id: load } // no property here
}
states: [
State {
name: "matrix"
PropertyChanges {
target: load
sourceComponent: tab;
Layout.fillWidth: true; // the layout is set here
}
}
]
Component {
id:tab
Rectangle {
color: "red"
width:30
height:30;
}
}
}

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
}
}
}
}
}

auto KeyNavigation.tab for custom components "rectangle or item" in QML

in Qml there is auto key navigation for already known components like checkbox,textfield,button and etc , i have my custom component which is a item or rectangle and i want same functionality for it,without writing
KeyNavigation.tab: componentid
here is one of my custom controls :
Rectangle {
signal clicked
property alias font : icoText.font.family
property alias icon : icoText.text
property alias size : icoText.font.pixelSize
property alias toolTip : tooltipText.text
property string colorEnter :"#0481ff"
property string colorExit :"#00171f"
id: root
implicitWidth: 50
implicitHeight: 50
//width: childrenRect.width
radius: 0
//height: childrenRect.height
color: colorExit
state: "default"
Text {
id: icoText
text: ""
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 25
font.family: "fontawesome"
visible: text!= ""
color: "white"
}
ToolTip {
id:tooltipText
text: ""
delay: 500
timeout: 2000
visible: mouseArea.containsMouse && text!=""
font.family: "B Nazanin"
contentItem: Text {
text: tooltipText.text
font: tooltipText.font
color: "white"
}
background: Rectangle {
color: "#cc000000"
border.color: "black"
}
}
InnerShadow {
id:shadow
anchors.fill: icoText
radius: 1.0
samples: 17
horizontalOffset: 1
color: colorExit
source: icoText
visible: false
}
MouseArea{
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onEntered: root.color = colorEnter
onExited: root.color = root.state == "transparent"? "transparent" : root.colorExit
onPressed: {
shadow.visible = true
}
onReleased: {
shadow.visible = false
}
onClicked: {
root.clicked()
}
}
states: [
State {
name: "transparent"
PropertyChanges {
target: root
color:"transparent"
}
PropertyChanges {
target: icoText
color:colorExit
}
},
State{
name: "default"
PropertyChanges {
target: root
color:colorExit
}
PropertyChanges {
target: icoText
color:"white"
}
}
]
}
which will be inside a page like this :
Item{
myControl{
}
myControl{
}
}
this component by default does not loop through pressing tab what should i do?
i already tried this without success, i think this should be inside FocusScope but cause of poor documentation i did not get a simple example for this
set activeFocusOnTab on parent and focus:true in child you want to get focus
Rectangle{
activeFocusOnTab: true
Control{
focus: true
}
}
Focusable Qml Components (Focus My Control On Tab)
For my experience key navigation only works with native components like checkbox, textfield, button, etc.
To work arround this problem I used a fake native component hided with the same size of my custom component like the next example:
Rectangle {
id: myCustomComponent1
width: 100
height: 100
color: red
Button {
id: buttonFake1
text: "My Accessible text Component 1"
width: parent.width
height: parent.height
opacity: 0 // hide the fake component
Accessible.role: Accessible.defaultButton
Accessible.name: text
KeyNavigation.tab: buttonFake2
onClicked: {
console.log(index)
}
onFocusChanged: {
if(focus === true){
// Here do what you want with your custom component
// For example, change color, size, ...
Do_what_you_Want()
// And then set back the focus at the fake native component
// to key navigation keeps working from the same component
buttonFake1.focus = true
}
}
}
}
Rectangle {
id: myCustomComponent2
width: 100
height: 100
color: green
Button {
id: buttonFake2
text: "My Accessible text Component 2"
width: parent.width
height: parent.height
opacity: 0 // hide the fake component
Accessible.role: Accessible.defaultButton
Accessible.name: text
KeyNavigation.tab: buttonFake1
onClicked: {
console.log(index)
}
onFocusChanged: {
if(focus === true){
// Here do what you want with your custom component
// For example, change color, size, ...
Do_what_you_Want()
// And then set back the focus at the fake native component
// to key navigation keeps working from the same component
buttonFake2.focus = true
}
}
}
}

Why when I open Dialog it will disable all qml item

I have a custom dialog in my qt quick application,when I click a button to open the it,I will got the below error:
QQuickItem::stackBefore: Cannot stack before 0x6d4bd6e220, which must be a sibling
After this error,All qml Items on the main.qml page will disable and don't work and don't interact width mouse.
main.qml
onClicked: {
var c= userPorfileCom.createObject(mainWindow);
c.open();
}
Component{
id:userPorfileCom
UserProfilePage{
id: userProfilePage
}
}
UserProfilePage.qml
JooyaDialog{
id: root
IranSanseFontLoader{
id: fl
}
onVisibleChanged: {
if(visible)
{
up.getProfile();
}
}
header: ToolBar{
id: tbheader
Material.primary: "white"
Material.elevation:1
RowLayout{
anchors.fill: parent
ToolButton{
contentItem: Image {
source: "/images/close.png"
fillMode: Image.Pad
horizontalAlignment: Image.AlignHCenter
verticalAlignment: Image.AlignVCenter
}
onClicked: {
close();
}
}
}
}
signal profileHasChanged;
UserProfile{
id: up
name: tfName.text
lastName: tfLastName.text
gender: cbxGender.currentIndex==0
email: tfEmail.text
phoneNumber: tfMobile.text
onProfileChanged: {
loginManager.getUserInfo();
}
onMessageChanged: {
showMessage(message);
}
onIsProcessingChanged: {
console.log("progr in user info");
bipi.visible=isProcessing;
}
}
title: qsTr("ویرایش اطلاعات کاربری")
rootWidth:mainWindow.width
rootHeight: mainWindow.height
contentHeight:rootHeight/2
font{
family: fl.name
pixelSize: 18
bold: true
}
//================================================
Flickable{
id: flickable
contentHeight: mainClm.implicitHeight+100
flickableDirection: Flickable.AutoFlickIfNeeded
clip: true
anchors.fill: parent
Pane{
anchors.fill:parent
Material.accent: Material.Pink
ColumnLayout{
id: mainClm
anchors.fill: parent
JooyaTextField{
id: tfName
placeholderText: "نام"
Layout.fillWidth: true
text: up.name
}
JooyaTextField{
id: tfLastName
placeholderText: "نام خانوادگی"
Layout.fillWidth: true
text: up.lastName
}
ComboBox {
id: cbxGender
model: ["مرد", "زن"]
anchors.horizontalCenter: parent.horizontalCenter
Layout.fillWidth: true
currentIndex:
{
if(up.gender)
{
return 0// "مرد"
}
else
{
return 1//"زن"
}
}
}
JooyaTextField{
id: tfMobile
placeholderText: "شماره موبایل"
Layout.fillWidth: true
text: up.phoneNumber
inputMethodHints: Qt.ImhDigitsOnly
}
JooyaTextField{
id: tfEmail
placeholderText: "ایمیل"
Layout.fillWidth: true
text: up.email
}
JooyaButton{
id: btnSave
text: "ذخیره"
Layout.fillWidth: true
highlighted: true
onClicked: {
up.saveProfile();
}
}
}
}
ScrollBar.vertical: ScrollBar{
width: 3
}
}
ProgressIndicator{
id: bipi
}
}
If two items are in the tab focus chain while not being siblings it won't work,
meaning that what is in the tab focus chain must have the same immediate parent.
http://doc.qt.io/qt-5/qquickitem.html#stackBefore

How to disable drag&drop for first Item of a ListView in QML

I have a QML project where I am able to drag & drop rectangles that are in a ListView.
I want to disable the drag&drop feature for the first Item (rectangle) of the ListView.
Here is an example:
Rectangle {
visible: true
width: 1000; height: 1000
ListView {
id: root
width: parent.width; height: parent.height
model: DelegateModel {
id: visualModel
model: myModel
model: ListModel {
id: colorModel
ListElement { someData }
...
}
delegate: MouseArea {
property int visualIndex: DelegateModel.itemsIndex
id: delegateRoot
cursorShape: Qt.PointingHandCursor
width: root.width; height: 100
drag.target: icon
drag.axis: Drag.YAxis
drag.minimumY: 0
property bool current: false
Rectangle {
blablaData
//Something like : if firstItem, disable drag&drop
}
onClicked: {
delegateRoot.current = !delegateRoot.current;
if(current) {
delegateRoot.height = 300
}
else {
delegateRoot.height = 100
}
}
Rectangle {
id: container
anchors.top: icon.bottom
width: root.width-5
height: delegateRoot.height - icon.height
clip: true
border.color: "#81BEF7"
Behavior on implicitHeight {
PropertyAnimation { duration: 100 }
}
Text {
anchors.fill: parent
anchors.margins: 10
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
text: size
}
}
DropArea {
anchors { fill: parent; margins: 15 }
onEntered: {
visualModel.items.move(drag.source.visualIndex, delegateRoot.visualIndex)
}
}
}
}
}
}
Do you have any idea of how to do it ?
Thanks a lot !
EDIT: Added some features to my example
In the delegate root item, try:
enabled: index ? true : false
I found an easy way to do it, and you can use it for the item you want (not only the first one).
I need to change drag.target and drag.axis in delegateRoot by using and setting a boolean like isDraggable to true or false on each item and then use it like this:
drag.target: isDraggable ? content : undefined
drag.axis: isDraggable ? Drag.YAxis : Drag.None

Custom Button inheritance (like in OOP rules)

I have made custom Button in QML and I want it to be the base item for all buttons in my project. What I want is to derive (like in OOP) buttons from it to change functionality. At first, every derived button should have its own onClicked response.
Is this possible in QML and if it is, how?
It's possible.
Here is an example of my BaseButton type. When BaseButton is clicked it emits a custom signal, in my code it's sgnClicked.
BaseButton.qml
import QtQuick 2.0
Item {
id:idButton
signal sgnClicked()
signal sgnClickMaintained()
signal sgnEntered()
signal sgnExited()
signal sgnReleased()
signal sgnPressed()
signal sgnCanceled()
property alias label: idText
property alias text: idText.text
property string iconSourceUp:""
property string iconSourceDown:""
property string iconSourceDisabled:""
property alias backgroundWidth: background.width
property alias backgroundHeight: background.height
property alias backgroundRect: backgroundRect
property alias hover: touchArea.enabled
width: 100
height: 20
Text{
id:idText
//text: "Button"
color:"white"
anchors.centerIn: parent
font.pointSize: 12
}
//if maintained at each 300 ms resend signal
Timer{
id:timer
running: false
repeat: true
interval: 300
onTriggered: sgnClickMaintained()
}
Image{
id:background
z: -1
width: parent.width
height: parent.height
source:iconSourceUp
visible: source.toString() !== ""
}
Gradient {
id:idGradient
GradientStop { position: 0 ; color: touchArea.pressed ? "#ccc" : "#eee" }
GradientStop { position: 1 ; color: touchArea.pressed ? "#aaa" : "#ccc" }
}
Rectangle {
id: backgroundRect
width: parent.width
height: parent.height
border.color: "#888"
color: enabled ?"":"lightgrey"
radius: 4
z: -1
visible: !background.visible
gradient: enabled ?idGradient:null
}
MouseArea{
id: touchArea
anchors.fill: parent
hoverEnabled: true
onCanceled: idButton.sgnCanceled()
onClicked:
{
idButton.sgnClicked()
}
onEntered: idButton.sgnEntered()
onExited: idButton.sgnExited()
onPressAndHold: {
timer.restart()
idButton.sgnClickMaintained()
}
onReleased:{
idButton.state = "up"
timer.stop()
idButton.sgnReleased()
}
onPressed:
{
idButton.state = "down"
idButton.sgnPressed()
}
}
onEnabledChanged: {
if(enabled === false)
{
idButton.state = "disabled"
timer.stop()
}
else{
idButton.state = "up"
}
}
states: [
State {
name: "down"
PropertyChanges {
target: background
source: iconSourceDown
}
},
State {
name: "disabled"
PropertyChanges {
target: background
source: iconSourceDisabled
}
},
State {
name: "up"
PropertyChanges {
target: background
source: iconSourceUp
}
}
]
Component.onCompleted:{
if(enabled)
{
state = "up"
}
else
{
state = "disabled"
}
}
}
To make a new Button inheriting from BaseButton you should instantiante the BaseButton as root item and in the slot onSgnClicked write what you want your button should do when clicked.
CustomButton.qml
import QtQuick 2.0
BaseButton {
width: 100
height: 50
onSgnClicked: {
//do something
}
}

Resources