I'm making a game and I want the theme soundtrack to be autoplayed and to keep on looping no matter what is the viewed page/stack status...etc how do I do this? I already have:
App {
onInitTheme: {
Theme.navigationBar.titleColor = "transparent"
Theme.navigationBar.height = 0
nativeUtils.preferredScreenOrientation = NativeUtils.ScreenOrientationPortrait
}
StackView {
id: stack
initialItem: mainView
anchors.fill: parent
}
Component{
id: mainView //first scene
Rectangle{
id: canvas
anchors.fill: parent
color: "black"
Image {
id: continueOW
source: "../assets/continueWOSigning.svg"
anchors.centerIn: parent
MouseArea{
anchors.fill: parent
onClicked: stack.push(playarea)
}
}
}
Component{
id: playarea //second scene
Rectangle{
id: playfield
anchors.fill: parent
color: "black"
Image {
id: go_back
source: "../assets/go_back.svg"
anchors.centerIn: parent
MouseArea{
anchors.fill: parent
onClicked: stack.push(mainView)
}
}
}
}
}
}
I know I should be using something like this:
Audio{
id: win
source: "../android/assets/win.wav"
}
But where do I put it so it's visible to all scenes?
If you want the Audio object lives as long as the App object lives, you can simply make it a direct child of the App.
Here is an example:
App {
onInitTheme: {
Theme.navigationBar.titleColor = "transparent"
Theme.navigationBar.height = 0
nativeUtils.preferredScreenOrientation = NativeUtils.ScreenOrientationPortrait
}
//YOU OTHER CODES
Audio{
source: "../android/assets/win.wav"
autoPlay: true
loops : Audio.Infinite
}
}
By setting autoPlay to true, autoLoad would be overwritten to true as well.
You are loading your .wav file from the assets directory. You could also make the same file available in the .qrc.
Related
We are having an ApplicationWindow based main.qml which is connected to our python backend via QmlElement Bridge. We have a view Slot-methods which directly return values to the qml frontend to change textfields which are children of the ApplicationWindow like the following:
ApplicationWindow {
id: mainFrame
width: 1280
height: 720
visible: true
title: qsTr("Test")
StackView {
id: stack
initialItem: loginFrame
anchors.fill: parent
}
Bridge {
id: bridge
}
Component{
id: loginFrame
ColumnLayout {
anchors.margins: 3
spacing: 3
Layout.columnSpan: 1
Layout.alignment: Qt.AlignHCenter
Text {
id: title
Layout.alignment: Qt.AlignHCenter
font.pointSize: 16
text: "Login Screen"
Layout.preferredHeight: 100
}
Button {
id: loginButton
Layout.alignment: Qt.AlignHCenter
text: "login"
highlighted: true
Material.accent: Material.Red
onClicked: {
title.text = bridge.login(username.text, password.text)
}
}
}
}
}
To reduce the size of our main.qml we decided to load the other Layouts, Components etc from different files with
Loader {
id: otherLoader
source: "other.qml"
}
How to access the Text Object inside of other.qml to update the text property from main.qml because the value is provided by the Bridge?
I already tried Accessing TextField from Another QML File but this hasn't worked.
The Loader creates items in not the same context as the statically create item use so cannot access the loaded item. You have several ways to access such an item.
The first and the most correct way is to use a declarative style:
Item {
id: container
anchors.fill: parent
property string someText: "press again"
Loader {
id: loader
active: false
sourceComponent: Text {
id: txt
text: container.someText
}
}
MouseArea {
anchors.fill: parent
onClicked: {
if(loader.active)
container.someText = "some text"
else
loader.active = true
}
}
}
You can create a binding in a Javascript code whenever you want:
Loader {
id: loader
active: false
sourceComponent: Text {
id: txt
Component.onCompleted: {
txt.text = Qt.binding(function() { return container.someText; })
}
}
}
Another option is using Loader.item property:
Item {
id: container
anchors.fill: parent
property string someText: "some text"
Loader {
id: loader
active: false
sourceComponent: Text {
id: txt
text: "press again"
}
}
MouseArea {
anchors.fill: parent
onClicked: {
if(loader.active)
loader.item.text = "some text"
else
loader.active = true
}
}
}
The following code works and shows my items correctly, but I get the warning
qrc:/TableDelegate.qml:24: ReferenceError: name is not defined
I think it is because the ListView tries to access the model when it is empty and can not reference the item properties. I assume I am not doing to it correctly but I do not know how to do it better.
So my question is: how to get rid of the warning by doing it the right way?
TableDelegate.qml:
import QtQuick 2.0
import QtQuick.Layouts 1.1
Item {
property color bgcolor: 'transparent'
property alias box: rowBox
height: 40
width: parent.width
Rectangle {
id: rowBox
anchors.fill: parent
color: bgcolor
RowLayout {
anchors.fill: parent
Rectangle {
id: tableNameColumn
color: 'transparent'
Layout.fillHeight: true
Layout.fillWidth: true
Text {
anchors.centerIn: parent
color: textcolor
text: name // <--- here is `name`
}
}
// More Columns ...
}
}
MouseArea {
anchors.fill: parent
onClicked: {
view.currentIndex = index
}
}
}
And I use it like this
TableView.qml:
// ...
ListModel {
id: model
}
ListView {
id: view
model: model
anchors.fill: parent
highlight: delegate_highlighted
highlightFollowsCurrentItem: true
delegate: delegate
}
Component {
id: delegate
TableDelegate {
bgcolor: 'transparent';
}
}
Component {
id: delegate_highlighted
TableDelegate {
bgcolor: 'lightsteelblue'
box.border.color: 'black'
box.radius: 3
}
}
// ...
You use a TableDelegate for the highlight. That is wrong.
The ListView creates 1 instance of the highlight item, that will be drawn as a background for the currently selected item, It may also move between items as transition when the current item changes. It should only be a rectangle or whatever you want to use.
In your example, the highlight item is a full delegate, that wants to access model data, which it cannot.
I am using a ComboBox in QML and when populated with a lot of data it exceeds my main windows bottom boarder. From googling I have learned that the drop-down list of a ComboBox is put on top of the current application window and therefore it does not respect its boundaries.
Ideally I would want the ComboBox to never exceed the main applications boundary, but I can not find any property in the documentation.
A different approach would be to limit the number of visible items of the drop-down list so that it do not exceed the window limits for a given window geometry. I was not able to find this in the documentation either and I have run out of ideas.
Take a look to the ComboBox source code, the popup is of a Menu type and it doesn't have any property to limit its size. Moreover, the z property of the Menu is infinite, i.e. it's always on top.
If you Find no way but to use the ComboBox of Qt you can create two models one for visual purpose, I will call it visual model, you will show it in your ComboBox and the complete one , it will be the reference model. Items count in your VisualModel wil be equal to some int property maximumComboBoxItemsCount that you declare . you'll need o find a way that onHovered find the index under the mouse in the visualmodel if it's === to maximumComboBoxIemsCount you do visualModel.remove(0) et visualModel.add(referenceModel.get(maximum.. + 1) and you'll need another property minimumComboBoxIemsCount, same logic but for Scroll Up , I dont know if it will work. but it's an idea
I think there is no solution using the built-in component and you should create your own comboBox. You can start from the following code.
ComboBox.qml
import QtQuick 2.0
Item {
id: comboBox
property string initialText
property int maxHeight
property int selectedItem:0
property variant listModel
signal expanded
signal closed
// signal sgnSelectedChoice(var choice)
width: 100
height: 40
ComboBoxButton {
id: comboBoxButton
width: comboBox.width
height: 40
borderColor: "#fff"
radius: 10
margin: 5
borderWidth: 2
text: initialText
textSize: 12
onClicked: {
if (listView.height == 0)
{
listView.height = Math.min(maxHeight, listModel.count*comboBoxButton.height)
comboBox.expanded()
source = "qrc:/Images/iconUp.png"
}
else
{
listView.height = 0
comboBox.closed()
source = "qrc:/Images/iconDown.png"
}
}
}
Component {
id: comboBoxDelegate
Rectangle {
id: delegateRectangle
width: comboBoxButton.width
height: comboBoxButton.height
color: "#00000000"
radius: comboBoxButton.radius
border.width: comboBoxButton.borderWidth
border.color: comboBoxButton.borderColor
Text {
color: index == listView.currentIndex ? "#ffff00" : "#ffffff"
anchors.centerIn: parent
anchors.margins: 3
font.pixelSize: 12
text: value
font.bold: true
}
MouseArea {
anchors.fill: parent
onClicked: {
listView.height = 0
listView.currentIndex = index
comboBox.selectedItem = index
tools.writePersistence(index,5)
comboBoxButton.text = value
comboBox.closed()
}
}
}
}
ListView {
id: listView
anchors.top: comboBoxButton.bottom
anchors.left: comboBoxButton.left
width: parent.width
height: 0
clip: true
model: listModel
delegate: comboBoxDelegate
currentIndex: selectedItem
}
onClosed: comboBoxButton.source = "qrc:/Images/iconDown.png"
Component.onCompleted: {
var cacheChoice = tools.getPersistence(5);
listView.currentIndex = tools.toInt(cacheChoice)
selectedItem = listView.currentIndex
comboBoxButton.text = cacheModel.get(selectedItem).value
}
}
ComboBoxButton.qml
import QtQuick 2.0
Item {
id: container
signal clicked
property string text
property alias source : iconDownUp.source
property string color: "#ffffff"
property int textSize: 12
property string borderColor: "#00000000"
property int borderWidth: 0
property int radius: 0
property int margin: 0
Rectangle {
id: buttonRectangle
anchors.fill: parent
color: "#00000000"
radius: container.radius
border.width: container.borderWidth
border.color: container.borderColor
Image {
id: image
anchors.fill: parent
source: "qrc:/Images/buttonBackground.png"
Image {
id: iconDownUp
source: "qrc:/Images/iconDown.png"
sourceSize.height:20
sourceSize.width: 20
anchors.verticalCenter: parent.verticalCenter
}
}
Text {
id:label
color: container.color
anchors.centerIn: parent
font.pixelSize: 10
text: container.text
font.bold: true
}
MouseArea {
id: mouseArea;
anchors.fill: parent
onClicked: {
container.clicked()
buttonRectangle.state = "pressed"
startTimer.start()
}
}
Timer{
id:startTimer
interval: 200
running: false;
repeat: false
onTriggered: buttonRectangle.state = ""
}
states: State {
name: "pressed"
when: mouseArea.pressed
PropertyChanges { target: image; scale: 0.7 }
PropertyChanges { target: label; scale: 0.7 }
}
transitions: Transition {
NumberAnimation { properties: "scale"; duration: 200; easing.type: Easing.InOutQuad }
}
}
}
I've used it in some software of mine, hence it is possible that It could not work "out of the box". I use it like this:
ComboBox{
id:cacheChoice
initialText: "None"
anchors.top: baseContainer.top
anchors.topMargin: 2
anchors.right: baseContainer.right
maxHeight: 500
listModel: cacheModel
onExpanded: {
cacheChoice.height = 500
}
onClosed: {
cacheChoice.height = 20
}
}
In case you are working with ComboBox from Qt Quick Controls 2, here's the source code for it:
https://github.com/qt/qtquickcontrols2/blob/5.12/src/imports/controls/ComboBox.qml
Based on that, this override of the behavior works to limit the height to something reasonable:
myComboBox.popup.contentItem.implicitHeight = Qt.binding(function () {
return Math.min(250, myComboBox.popup.contentItem.contentHeight);
});
It is possible to access the hidden MenuStyle within the ComboBoxStyle component. There you can use all the things and hidden things you have within a MenuStyle, including its maximum height.
The thing looks roughly like this.
Not pretty but it works well enough.
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.3
import QtQuick.Window 2.2
ComboBox {
id: comboBox
style: ComboBoxStyle {
// drop-down customization here
property Component __dropDownStyle: MenuStyle {
__maxPopupHeight: 400
__menuItemType: "comboboxitem" //not 100% sure if this is needed
}
}
As it came up resonantly in our team, here is a updated version of the idea shown above. The new version restricts the size automatically to the size of your application.
ComboBox {
id: root
style: ComboBoxStyle {
id: comboBoxStyle
// drop-down customization here
property Component __dropDownStyle: MenuStyle {
__maxPopupHeight: Math.max(55, //min value to keep it to a functional size even if it would not look nice
Math.min(400,
//limit the max size so the menu is inside the application bounds
comboBoxStyle.control.Window.height
- mapFromItem(comboBoxStyle.control, 0,0).y
- comboBoxStyle.control.height))
__menuItemType: "comboboxitem" //not 100% sure if this is needed
} //Component __dropDownStyle: MenuStyle
} //style: ComboBoxStyle
} //ComboBox
I have QtQuick 1.0
I use the following code:
Rectangle {
Component {
id: appDelegate
MouseArea{
id:myMouseArea
hoverEnabled: true
onClicked:{
onClicked: load.source = page;
}
}
Loader {
id: load
}
}
GridView {
id: view
// I am unable to access myMouseArea here.
highlight: myMouseArea.containsMouse ? appHighlight : !appHighlight
delegate: appDelegate
}
}
It gives me the following error:
ReferenceError: Can't find variable: myMouseArea
/usr/lib/i386-linux-gnu/qt4/bin/qmlviewer exited with code 0
I don't know if the details I provided are sufficient, please let me know if theres anything else I am missing.
I am using this code as an example:
http://docs.knobbits.org/qt4/declarative-modelviews-gridview-qml-gridview-example-gridview-example-qml.html
You cannot access myMouseArea because it's created inside delegate context. You cannot access delegate other then currentItem. But you can freely access view inside the context of delegate, to set currentIndex to attached property index.
This is a corrected code:
Rectangle {
width: 360
height: 360
Component { // It must be a component, if we want use it as delegate
id: appDelegate
// its not possible to have more than one element inside component
Rectangle
{
// need to set size of item, anchors wont work here
// could use view.cellWidth and view.cellHeight to keep it DRY
width: 96
height: 66
color: "green" // color only to see the place of MouseArea
MouseArea {
id:myMouseArea
anchors.fill: parent // this setup the size to whole rectangle
// it this item have the size 0,0 it will simple do not work
hoverEnabled: true
onEntered: {
// we know the mouse is inside this region
// setting this value will show the highlight rectangle
view.currentIndex = index;
}
onClicked:{
onClicked: load.source = page;
}
}
Loader {
// this is not needed but it's wise to not keep zero size
anchors.fill: parent
id: load
}
}
}
GridView {
id: view
// the size of GridView must be set,
// as otherwise no delegate will not show
anchors.fill: parent
anchors.margins: 5
cellWidth: 100
cellHeight: 70
// Rectangle will act as a border.
// Size and position is set by GridView
// to the size and position of currentItem.
// This is no a item, this makes a Component
// as highlight property needs one.
// You can create a Component like appDelegate.
highlight : Rectangle {
border.width: 2
border.color: "blue"
}
// some ListModel to setup the page variable inside delegate context
model: ListModel {
ListElement { page: "test1.qml"; }
ListElement { page: "test2.qml"; }
ListElement { page: "test3.qml"; }
}
delegate: appDelegate
}
}
I have problem in binding item in QML, for example:
Rectangle{
id: thetarget
width:100
height:100
}
Item{
id: container
MouseArea{
id:mousearea
drag.target: thetarget //not work
anchors.fill: thetarget //not work
property int foo: thetarget.width //work
}
}
What I want is to make the bindings for drag.target, anchors.fill work without changing the structure (mousearea is not the sibling or child of thetarget). I have used Binding, function to return thetarget, but they are all useless. Could someone tell me what's wrong?
Set the parent of the mousearea to thetarget.
import QtQuick 1.1
Item {
Rectangle {
id: thetarget
width: 100
height: 100
}
Item {
id: container
MouseArea {
id: mousearea
parent: thetarget
drag.target: thetarget
anchors.fill: thetarget
property int foo: thetarget.width
}
}
}