I am making a music player application. i have a DownRect which has a slider and a playSection which has a button. this button has a audio. when button is clicked audio is played and i want the slider to set it's value by the audio duration. (the button is add dynamically from ButtonD.qml file). what i want to do is to connect DownRect's slider to playSection's button.
//DownRect.qml
Rectangle{
id: downRectangle
width: parent.width
height: parent.height
x:0
y:750
color: "#c62828"
smooth: true
Slider{
id: sliderDownRect
x: 300
y: 25
width: 650
from: 0
// to: play.duration
stepSize: 100
value: 0
Material.accent : Material.background
Material.foreground: Material.background
onValueChanged:{
}
}
}
and here is the ButtonD.qml file which i'd like to connect to DownRect.qml
//ButtonD.qml
Button{
id: buttonD
width:900
height: 46
flat: true
Audio{
id: playing
}
}
You make sure that the duration (and other relevant properties of Audio) are exposed in ButtonD.qml, e.g. by adding aliases like such:
Button {
id: buttonD
property alias duration: playing.duration
...
}
The same goes for the Slider's value.
Rectangle {
id: downRectangle
property alias duration: sliderDownRect.to
...
}
In the file that instantiates both, you use Binding-objects to create a bidirectional binding between the both. Those Binding-objects excell at working with dynamically instantiated objects.
Basically, if you'd include the files into one file, this should look something like this:
main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtMultimedia 5.5
ApplicationWindow {
id: myWindow
visible: true
width: 600
height: 600
color: 'white'
property Item dynamicallyCreatedItem
Button {
x: 102
text: 'create'
onClicked: {
dynamicallyCreatedItem = Qt.createComponent('AudioButton.qml').createObject(myWindow.contentItem)
}
}
DownRect {
y: 50
id: rect
}
Binding {
target: rect
property: 'maxValue'
value: dynamicallyCreatedItem ? dynamicallyCreatedItem.duration : 0
when: dynamicallyCreatedItem
}
Binding {
target: rect
property: 'value'
value: dynamicallyCreatedItem ? dynamicallyCreatedItem.position : 0
when: dynamicallyCreatedItem
}
}
AudioButton.qml
import QtQuick 2.0
import QtQuick.Controls 2.0
import QtMultimedia 5.5
Button {
id: audioButton
onClicked: audio.play()
property alias duration: audio.duration
property alias position: audio.position
Audio {
id: audio
source: 'airhorn.wav'
}
}
DownRect.qml
import QtQuick 2.0
import QtQuick.Controls 2.0
Rectangle {
id: rect
width: parent.width
height: 50
property alias value: slider.value
property alias maxValue: slider.to
Slider {
id: slider
anchors.fill: parent
}
}
Related
I have a frameless qml window with a custom window decoration I created. And I am trying to assign a DragHandler to the window decoration with the target being the window. But I a specific error and only the custom window decoration is being dragged inside the window, the rest of the window remains as it is (not being dragged).
Also this window decoration contains the maximize button which I defined myself, it perfectly works, however the taskbar cannot be accessed while the window is maximized.
Can anyone help me see what is going wrong here and fix this?
Here is the error I received
file:///D:/QML tutorial/Tutorial_UI/Tutorial_UI.qml:92:21: Unable to assign Tutorial_UI_QMLTYPE_11 to QQuickItem
And here is my code (window and the titlebar)
Window {
id: window
width: 640
height: 480
visible: true
title: qsTr("QNotepad")
property int previousX
property int previousY
color: "#272727"
flags: Qt.Window | Qt.FramelessWindowHint
TitleBar {
id: title_bar
color: (window.active) ? "#1A212B"Β :Β "#272727"
width: 645
height: 50
//draggable widget
DragHandler{
id: draghandler
target: window
}
Text {
id: titlebar_text
text: "QNotePad"
color: "white"
x: 20
y: 10
}
}
And my code for the maximize button
ToolbarButton {
id: max_btn
text: "π"
text_color: "white"
onClicked: {
window.visibility === Window.Maximized ? (window.showNormal(), max_btn.text = "π", title_bar.width = 645, title_bar.height = 50, tool_bar.width = 640, tool_bar.height = 50, close_btn.x = 595, max_btn.x = 545, min_btn.x = 505, view.height = 600, view.width = container.width) : (window.showMaximized(), max_btn.text = "π" , title_bar.width = Screen.width, tool_bar.width = Screen.width, close_btn.x = (Screen.width-45), max_btn.x = (Screen.width-95), min_btn.x = (Screen.width-135), view.height = (Screen.height-40), view.width = Screen.width)
}
x: 545
y: 0
}
```
Instead of using DragHandler, consider using MouseArea with drag.target set. e.g.
TitleBar {
MouseArea {
anchors.fill: parent
drag.target: window
}
}
Here's an example of MouseArea with drag.target working in a mock application:
import QtQuick
import QtQuick.Controls
Page {
background: Rectangle { color: "#8ac" }
NotePadApp {
id: app1
x: 200
y: 200
}
NotePadApp {
id: app2
x: 400
y: 100
}
}
// NotePadApp.qml
import QtQuick
import QtQuick.Controls
Page {
id: page
width: 400
height: 400
header: TitleBar {
MouseArea {
anchors.fill: parent
drag.target: page
}
}
Frame {
anchors.fill: parent
}
}
// TitleBar.qml
import QtQuick
import QtQuick.Controls
Rectangle {
width: parent.width
height: titleText.height + 20
color: "#888"
property string title: "QNotePad"
Text {
id: titleText
x: 10
y: 10
text: title
color: "white"
}
}
You can Try it Online!
Is it possible to transfer the same code logic in another page, in which these two images are taken as alias or something similar and they behave in the same pattern of "if statement" logic on the other QML file(2) when this button is pressed from the first QML file(1)?
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Studio.Components 1.0
import QtQuick.Timeline 1.0
Item {
id: root
width: 500
height: 500
property alias locking: locking
Text {
id: confirmSign
text: qsTr("")
anchors.left: parent.left
anchors.top: parent.top
font.styleName: "Bold"
anchors.leftMargin: 70
anchors.topMargin: 55
color: "white"
font.pointSize: 10
font.family: "Tahoma"
}
RoundButton {
id: locking
y: 70
width: 90
height: 90
anchors.left: password_field.right
anchors.leftMargin: 15
Image {
id: unlck
anchors.centerIn: parent
source: "Images/Unlocked.png"
visible: false
}
Image {
id: lcked
anchors.centerIn: parent
source: "Images/Locked.png"
visible: true
}
onClicked: {
passBlocker.visible = true
confirmSign.text = qsTr("The ToolBar is 'Locked' ");
confirmSign.color = "#ffffff";
lcked.visible = true
unlck.visible = false
}
}
}
You can create a new file just for the lock image and use it wherever you want.
Something like this:
File LockImage.qml
Item {
property bool locked: false
Image {
id: lcked
anchors.centerIn: parent
source: locked? "Images/Locked.png": "Images/Unlocked.png"
visible: true
}
}
Side note: you donβt need to change properties using clicked handler. Prefer using the checked property of Button
I have created a custom virtual keyboard where the components are buttons, whose attributes I have defined in the code below . When I rapidly move the mouse across the buttons, I find that there is a 'flashing' effect whereby the button opacity appears to momentarily drop to 0 and then return. How can I prevent this flashing effect?
import QtQuick 2.15
import QtQuick.Controls 2.12
import QtGraphicalEffects 1.0
import "definitions.js" as Defs
Button {
id: keyboardButton
property bool specialButton: false
contentItem: Text {
text: keyboardButton.text
font.family: Defs.font
font.pointSize: Defs.defaultTextSize
color: Defs.ivory
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
id: background
property double op: specialButton ? 0.7 : 0.5
color: Defs.b_blue
opacity: op
radius: 0
OpacityAnimator on opacity{
running: keyboardButton.hovered
from: background.opacity
to: background.op + 0.05
duration: 100
}
OpacityAnimator on opacity{
running: !keyboardButton.hovered
from: background.op + 0.05
to: background.op
duration: 100
}
}
}
Using one animator fixes it for me:
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
width: 640
height: 480
visible: true
Flow {
anchors.fill: parent
Repeater {
model: 100
Button {
id: keyboardButton
property bool specialButton: false
contentItem: Text {
text: keyboardButton.text
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
color: "steelblue"
opacity: hovered ? baseOpacity + 0.15 : baseOpacity
radius: 0
property double baseOpacity: keyboardButton.specialButton ? 0.7 : 0.5
Behavior on opacity {
OpacityAnimator {
duration: 100
}
}
}
}
}
}
}
This question is similar to - but no the same as Moving qml Item out of left side of window, because my question is about Dialogs, instead of Items in general. The difference is explained below.
I have a Qt Dialog which I want to enter the screen from the left.
The first approach I took was setting the dialogs x property to -width and then adding a Behavior on x or a manually triggered NumberAnimation.
This approach however failed, because setting negative x values is not allowed and the value gets changed to 0 immediately.
This post provides a solution for this issue, by using anchors and AnchorChanges and transitions - but only for Items.
However, the Dialog type does neither provide states, nor anchors but only coordinates.
So my question stands: How can I have a QML Dialog animate from the left outside the screen into view?
Here's a minimal code sample, that demonstrate the x property being reset to 0:
import QtQuick 2.7
import QtQuick.Controls 2.3
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Dialog Demo")
Dialog {
id: dialog
width: 200
height: 200
x: -width
Text {
anchors.centerIn: parent
text: "Ok?"
}
standardButtons: Dialog.Ok
onOpened: x = 100
Behavior on x { NumberAnimation{ duration: 1000 } }
}
Component.onCompleted: dialog.open()
}
You can use the enter-transition that is inherited from Popup:
import QtQuick 2.9
import QtQuick.Window 2.0
import QtQuick.Controls 2.3
Window {
id: window
visible: true
width: 600
height: 600
Dialog {
id: dialog
width: 300
height: 300
enter: Transition {
NumberAnimation { properties: "x,y"; from: -300; to: 150 }
}
}
Button {
anchors.centerIn: parent
onClicked: dialog.open()
}
}
There seems to be a Bug with the Dialog. As soon as the Dialog has some content, it fails. I have not discovered all depths of it, but wrapping everything in an Item seems to help. Compare for this:
import QtQuick 2.9
import QtQuick.Window 2.0
import QtQuick.Controls 2.3
ApplicationWindow {
id: window
visible: true
width: 600
height: 600
Dialog {
id: dialog
width: 300
height: 300
enter: Transition {
NumberAnimation { properties: "x,y"; from: -300; to: 150; duration: 5000 }
}
// HAVE A BUTTON IN THE DIALOG -> POSITIONING FAILS
Button {
anchors.centerIn: parent
}
}
Button {
text: 'open'
anchors.centerIn: parent
onClicked: dialog.open()
}
}
and
import QtQuick 2.9
import QtQuick.Window 2.0
import QtQuick.Controls 2.3
ApplicationWindow {
id: window
visible: true
width: 600
height: 600
Dialog {
id: dialog
width: 300
height: 300
enter: Transition {
NumberAnimation { properties: "x,y"; from: -300; to: 150; duration: 5000 }
}
Item { // WRAP IT IN THE ITEM -> WORKS FOR ME
anchors.fill: parent
Button {
anchors.centerIn: parent
}
}
}
Button {
text: 'open'
anchors.centerIn: parent
onClicked: dialog.open()
}
}
I have a ToolButton in QML with an image with size 48x48 pixels:
ToolButton {
contentItem: Image {
source: "Icons/idea48.png"
}
}
if I set width and height nothing changes:
ToolButton {
contentItem: Image {
source: "Icons/idea48.png"
width: 5
height: 5
}
}
on the screen it is still 48x48.
And even adding fill Mode does not help:
ToolButton {
visible: scene.serviceMode
contentItem: Image {
source: "Icons/idea48.png"
width: 10
height: 10
fillMode: Image.Stretch
sourceSize: {
width: 48
height: 48
}
}
}
the sourceSize should be 48 to render image with high pixel density.
I also tried to put Image inside Item, but with no success:
ToolButton {
contentItem: Item {
width: 24
height: 24
Image {
source: "Icons/idea48.png"
fillMode: Image.Stretch
sourceSize: {
width: 48
height: 48
}
}
}
}
Qt Quick Controls 2.3 (Qt 5.10) adds built-in support for button icons. By default, different styles may request different icon sizes, according to their design guidelines, but you can easily override the icon size.
ToolButton {
icon.width: 24
icon.height: 24
icon.source: "Icons/idea48.png"
}
What comes to high-DPI support, consider providing #Nx versions like the Gallery example does: http://code.qt.io/cgit/qt/qtquickcontrols2.git/tree/examples/quickcontrols2/gallery/icons/gallery?h=5.10
Answer 1
Set the sourceSize of the Image in order to influence its implicitWidth and implicitHeight, which are used by the ToolButton to determine the size of the contentItem.
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
ApplicationWindow {
visible: true
width: 640
height: 480
header: ToolBar {
RowLayout {
anchors.fill: parent
ToolButton {
contentItem: Image {
source: "Icons/idea48.png"
sourceSize.width: 10
sourceSize.height: 10
fillMode: Image.Pad
}
}
}
}
}
Answer 2
Put the Image inside an Item so that the Image is not resized by the ToolButton and its dimensions remain exactly as specified by width and height.
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
ApplicationWindow {
visible: true
width: 640
height: 480
header: ToolBar {
RowLayout {
anchors.fill: parent
ToolButton {
contentItem: Item {
Image {
source: "Icons/idea48.png"
width: 10
height: 10
}
}
}
}
}
}
Answer 3
Force the size of the contentItem.
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
ApplicationWindow {
visible: true
width: 640
height: 480
header: ToolBar {
RowLayout {
anchors.fill: parent
ToolButton {
contentItem: Image {
source: "Icons/idea48.png"
}
Component.onCompleted: {
contentItem.width = 10
contentItem.height = 10
}
}
}
}
}