Create component like Page in QML, contains header-like Item - qml

We have a working code
Page {
header: Item {}
}
I need to create a new template component in which I can then put the necessary components, just as we write our component in the property of the header, that is, I'm interested in how to make my analog header template.

Found an answer.
Template file Some.qml:
import QtQuick 2.0
Item {
width: 500
height: 500
property alias content: column.children
Column {
id: column
anchors.fill: parent
}
}
and use it
import QtQuick 2.0
Some {
content: Rectangle {
width: parent.width
height: 100
color: "red"
}
}

Related

QML - How do I make the TabButtons in TabBar visible?

I'm using qtcreator 4.4.1 with qt 5.9.2-1 on linux
I'm trying to create a tabbar with a stackview so that I can switch between the different tabs. But the tabbuttons in the tabbar never show up, and they aren't functional either if I click the area where they should have been.
I've tried adding all sorts of colored rectangles to see if I could somehow bring it to the surface, but it never shows... And I also added visible: true on most of the components. Also I tried to make sure everything has a width and height. But nonetheless, I still am unable to see it.
This is what it looks like
import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Extras 1.4
import QtQuick.Layouts 1.3
import QtQuick.Templates 2.2
ApplicationWindow {
id: root
flags: Qt.FramelessWindowHint
visible: true
width: 382
height: 748
Column {
id: column1
width: parent.width
height: parent.height
visible: true
TabBar {
id: bar
width: parent.width
height: 50
visible: true
TabButton {
visible: true
text: qsTr("Fruit")
width: parent.width
height: parent.height
Rectangle {
anchors.fill: parent
color: "#ff0000"
visible: true
}
}
TabButton {
visible: true
text: qsTr("Vegetables")
width: parent.width
height: parent.height
Rectangle {
anchors.fill: parent
color: "#00ff00"
visible: true
}
}
TabButton {
text: qsTr("Demons")
width: parent.width
height: parent.height
Rectangle {
anchors.fill: parent
color: "#0000ff"
visible: true
}
}
}
StackLayout {
width: parent.width
height: parent.height
visible: true
currentIndex: bar.currentIndex
Item {
id: fruitTab
Rectangle {
anchors.fill: parent
color: "#ff0000"
visible: true
}
}
Item {
id: vegetableTab
Rectangle {
anchors.fill: parent
color: "#00ff00"
visible: true
}
}
Item {
id: demonTab
Rectangle {
anchors.fill: parent
color: "#0000ff"
visible: true
}
}
}
}
}
I also tried the simple example given by the qt docs: https://doc.qt.io/qt-5/qml-qtquick-controls2-tabbar.html#details but that didn't work either.
It looks like this
In addition to what #derM said (I would just leave out the width and height assignments altogether), the last import is a problem:
import QtQuick.Templates 2.2
Since the templates and controls have a one-to-one mapping of type names, this will cause the controls types to be shadowed by the ones from templates (since the templates import comes last).
You should always import the templates into their own namespace if you're also importing the controls:
import QtQuick.Templates 2.2 as T
http://doc.qt.io/qt-5/qtqml-syntax-imports.html#import-types explains this in detail:
This import allows multiple modules which provide conflicting type names to be imported at the same time, however since each usage of a type provided by a module which was imported into a qualified namespace must be preceded by the qualifier, the conflict is able to be resolved unambiguously by the QML engine.
In your example it looks like you're not using the templates at all, so you can just remove the import.
Try to remove the width in your TabButtons.
The problem seems to be, the dynamic sizing of the buttons.
You set them to be of the same width as the tab bar. So each button would fill the whole bar on its own.
When it tries to layout this, it obviously fails.
The same goes, if you set all of them, e.g. to width = parent.width / 2 as the parent's width is determined by the width of the children.
You need to either set the width of the buttons in relation to the TabBars width, by using myTabBarsId.width or you can just leave it out and let it be sized dynamically.
TabBar {
id: bar
width: parent.width
height: 50
visible: true
TabButton {
width: bar.width / 2 // Define width based on the `TabBar` width
text: qsTr("Fruit")
height: parent.height
}
TabButton {
text: qsTr("Vegetables")
height: parent.height
}
TabButton {
text: qsTr("Demons")
height: parent.height
}
}

How to Connect two qml files?

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

Qml nested row/repeater in a column/repeater

I am trying to create two rows of rectangles using a row/repeater within a column/repeater. The results I am seeing are that the rows of rectangles are stacked on top of each other. I expected to see a blue row of rectangles with a green row of rectangles beneath the blue row. It seems like this should be possible. Any ideas on what I am doing wrong?
I think a code example will help illustrate what I am trying to accomplish.
Here is my main.qml
import QtQuick 2.2
Rectangle {
visible: true
width: 640
height: 480
color: 'black'
border.color: 'white'
RectRow {
id: rectRow
startX: 10
startY: 10
rectVals: [{count: 4, color: 'blue'}, {count: 2, color: 'green'}]
}
}
Here is my RectRow.qml
import QtQuick 2.2
Item {
property var rectVals
property alias startX: rectCol.x
property alias startY: rectCol.y
property string rectBorderColor: '#ffffff'
Column {
id: rectCol
Repeater {
id: repeater
model: rectVals
Item {
height: 50
Row {
property string rectColor: modelData.color
Repeater {
model: modelData.count
Rectangle {
width: 100
height: 50
color: parent.rectColor
border.color: rectBorderColor
}
}
}
}
}
}
}
As in QML Form layout (GridLayout) troubles, you need to give the Item a width:
import QtQuick 2.2
Item {
property var rectVals
property alias startX: rectCol.x
property alias startY: rectCol.y
property string rectBorderColor: '#ffffff'
Column {
id: rectCol
Repeater {
id: repeater
model: rectVals
Item {
width: row.width
height: 50
Row {
id: row
property string rectColor: modelData.color
Repeater {
model: modelData.count
Rectangle {
width: 100
height: 50
color: parent.rectColor
border.color: rectBorderColor
}
}
}
}
}
}
}
Or just remove it altogether; it doesn't seem to be necessary.

Hide the highlight of a ListView while scrolling

I am building a Qt5 application based on Qt-Quick 2 for the UI. I have an issue while displaying a ListView with an highlight component. When I scroll the ListView the highlight rectangle is visible outside of the ListView and I can't find a way to avoid it.
Here is an example of the issue with a minimal QML file:
import QtQuick 2.0
Rectangle {
width: 360; height: 600
ListView {
width: 350; height: 200
anchors.centerIn: parent
id: myList
model: myModel
highlight: highlightBar
delegate: Item {
width: 400; height: 20
Text { text: name }
MouseArea {
id: mArea
anchors.fill: parent
onClicked: { myList.currentIndex = index; }
}
}
}
Component {
id: highlightBar
Rectangle {
width: parent.width; height: 20
color: "#FFFF88"
}
}
ListModel {
id: myModel
}
/* Fill the model with default values on startup */
Component.onCompleted: {
for(var i = 0; i < 100; i++) {
myModel.append({ name: "Big Animal : " + i});
}
}
}
Is there a way to "limit" a component to its parent borders or to hide the highlight component while scrolling?
As reported by the documentation:
Note: Views do not enable clip automatically. If the view is not clipped by another item or the screen, it will be necessary to set clip: true in order to have the out of view items clipped nicely.
Hence, what you are experiencing is a common behaviour and you should either 1) clip the view via other Items (e.g. a header Rectangle and a footer Rectangle with z:infinite or simply set the clip property to true, i.e.
ListView{
//...
clip:true
//...
}
Clipping has some perfomance disavantages which can greatly affect the application as it grows. Hence, its usage, especially outside the views scenario, should be evaluated carefully.

item inside component access

I have the following qml file:
import QtQuick 1.0
Component{
Column{
id: interHeader;
Item{
id:interItem
height: 300
width: 200
Text{
id:title
text:"Text"
anchors.centerIn: parent
font.bold: true
elide:"ElideRight"
color: "Black"
}
}
Item {
width: parent.width
height: 100
//onClick event
MouseArea {
anchors.fill: parent
onClicked:{
console.log("Ok");
}
}
}
}
}
The problem is that I need to assign some KeyNavigation to the interItem.
I want to access the interItem from another qml file.
How can this be done?
There really is no benefit of using Component in a completely separate QML file. Remove Component and name your Qml file with a capital letter - e.g. InterHeader
Then define a property under your root item. For example:
import QtQuick 1.0
Item {
id: interHeader
property variant keyActionUp
Keys.onUpPressed: keyActionUp
}
OR
You can use the Connections function to execute callbacks for signals from interHeader.
http://doc.qt.nokia.com/4.7-snapshot/qml-connections.html