Custom QML Quick 2 Control with TabBar Inside - qt

I am creating a custom QML Quick 2 TabBar control in Qt 5.15. If I make a simple control (CustomTabBarSimple.qml) as
import QtQuick 2.0
import QtQuick.Controls 2.15
TabBar {
}
Then I can use it with
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
Window {
visible: true
width: 640; height: 480
color:"silver"
CustomTabBarSimple
{
id:bar
TabButton { text:"Button1" }
TabButton { text:"Button2" }
}
StackLayout {
anchors.top: bar.bottom
currentIndex: bar.currentIndex
Text {text: "First Stack"}
Text {text: "Second Stack"}
}
}
But if instead I wrap the TabBar in another control like this is no longer functions:
import QtQuick 2.0
import QtQuick.Controls 2.15
Rectangle
{
default property alias contents: bar.data
width: 300; height:50
color: "red"
TabBar {
id: bar
}
}
You can see I tried to use default property alias contents: bar.data to put the TabButton inside the custom control's TabBar but it appears that the TabBar no longer organizes the buttons properly and they no longer change the currentIndex when clicked---likely because the data field is overwriting critical elements.
Is it possible to inject the TabButton into the proper place using a default alias? Second, how would I be able to discover this for myself from the documentation?

There's two problems with your code:
You're trying to access currentIndex from the TabBar, but you're not exposing that property in your CustomTabBarSimple. You can fix that by adding this:
property alias currentIndex: bar.currentIndex
The list of TabButtons are not direct children of the TabBar. TabBar is derived from a Container, which has a list of child objects in contentData. You can read about that here.
default property alias contents: bar.contentData

Related

How to change triangle in ComboBox qml?

How do I change the size and color of the triangle in a ComboBox? And also flip the triangle?
Now it looks like this
I'm assuming you're using the Material style.
Without declaring your own indicator:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
id: window
width: 640
height: 480
visible: true
ComboBox {
id: comboBox
model: 10
Binding {
target: comboBox.indicator
property: "rotation"
value: 180
}
Binding {
target: comboBox.indicator
property: "color"
value: "tomato"
}
}
}
Declaring your own indicator:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
id: window
width: 640
height: 480
visible: true
ComboBox {
id: comboBox
model: 10
indicator: ColorImage {
x: comboBox.mirrored ? comboBox.padding : comboBox.width - width - comboBox.padding
y: comboBox.topPadding + (comboBox.availableHeight - height) / 2
color: "tomato"
rotation: 180
source: "qrc:/qt-project.org/imports/QtQuick/Controls/Material/images/drop-indicator.png"
}
}
}
Both approaches assume something about the QML implementation of the style in use:
The first approach assumes that the indicator has a color property. This could change in a future version (although it's very unlikely).
The second approach uses an internal resource URL (for convenience, since it's an image that everyone testing this code should have available on their machines), but I wouldn't generally encourage doing so yourself. If you're sure that your application will use the Material style, then it should be fine, but again, this path could change in a future version. If you want a more future-proof option, use your own image for the indicator.
If you want a completely future-proof option, implement your own style:
https://doc.qt.io/qt-5/qtquickcontrols2-customize.html#definition-of-a-style
Qt 6 version of that page:
https://doc.qt.io/qt-6/qtquickcontrols2-customize.html#definition-of-a-style

QML Glow Inside a RowLayout

I am using Qt 5.15 Quick 2 QML to create a row of custom buttons in a window. When I have a standalone custom button things appear to work fine, but when I put them in a RowLayout there appears to be severe clipping and artifacting issues.
A minimum reproducible example might look like:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
RowLayout
{
anchors.fill:parent
anchors.margins: 25
Button
{
text: "Click Me"
Layout.fillWidth: true
}
CustomButton
{
text: "That Boy Don't Glow Right"
}
Button
{
x: 100; y:100
text: "Click Me"
Layout.fillWidth: true
}
}
}
with the custom control
import QtQuick 2.0
import QtQuick.Controls 2.15
import QtGraphicalEffects 1.15
Button {
id: control
text: "Click Me"
Glow {
anchors.fill: control
radius: 64
spread: 0
samples: 128
color: "red"
source: control
visible: true
}
}
with example output:
One potential fix is to add change the Glow to
Glow {
anchors.fill: control
width: parent.width
height:parent.height
x:control.x
y:control.y
parent: control.parent
...
But this doesn't seem right. First, it's not obvious to me where parent.width and control.x and control.parent are bound from and what happens in single and multiple nesting. If a CustomButton is placed inside another control with id control, would it rebind the property? And it appears if a RowLayout is placed inside a RowLayout, then it would require parent: control.parent.parent. In my actual code there is some non-trivial positioning to allow margins for a drop shadow, too, and the CustomButton is in another container so the actual code that works is: x:control.x + parent.pad/2 and parent:control.parent.parent.parent which is, frankly, ridiculous and assumes that non-standard fields in the parent are always available.
Is there a better way? Was hoping I could keep the button's ability to glow itself.
According to the docs:
"Note: It is not supported to let the effect include itself, for instance by setting source to the effect's parent."
So it's fortunate that you were able to get your example to work at all. One way to avoid using the parent as a source is to point the Glow object at the Button's background object:
Button {
id: control
Glow {
source: control.background
}
}

QML Dialog positioning in ApplicationWindow

I am finding it impossible to position a Dialog central to my ApplicationWindow in QT 5.12
import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Dialogs 1.2
ApplicationWindow {
id:mainApplicationWindow
visible: true
height: 500
width: 500
Item {
anchors.centerIn: parent
MainWindowMessageDialog{
id: messageDialog
}
}
Component.onCompleted: {
messageDialog.open()
}
}
With MainWindowMessageDialog.qml
import QtQuick 2.0
import QtQuick.Dialogs 1.2
Dialog {
title: "There seems to be a problem"
standardButtons: StandardButton.Ok
onAccepted: {
this.close()
}
}
Gives me the image below. I've tried adding a fixed z position but nothing seems to shift the Dialog downwards into the window. I've tried MainWindowMessageDialog on its own outside of an Item. Nothing seems to shift it? Am I missing something?
This turned out to be an issue of modality.
https://bugreports.qt.io/browse/QTBUG-82737?jql=text%20~%20%22MessageDialog%22
Adding
modality: Qt.ApplicationModal
Did the trick

Can't set text field to fill width in QML

I am following this tutorial on YouTube and the person sets the TextField to fill the width of the RowLayout. However, it doesn't seem to work for me. I tried using Layout.fillWidth on the CheckBox and it seems to work perfectly fine but it doesn't seem to want to work on the TextField. Here is my code:
main.qml:
import QtQuick 2.9
import QtQuick.Controls 2.2
ApplicationWindow
{
visible: true;
width: 640;
height: 480;
title: qsTr("Tabs");
ToDoList
{
anchors.centerIn: parent;
}
}
ToDoList.qml:
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
Frame
{
ListView
{
// Using implicit width and height allows the frame to automatically scale to the size of the list view
implicitWidth: 250
implicitHeight: 250
clip: true
model: 100
delegate: RowLayout {
width: parent.width
CheckBox {}
TextField
{
Layout.fillWidth: true
}
}
}
}
Here is a screenshot of what mine looks like
What did I do wrong?
I don't know if this has anything to do with it but I made a "Qt Quick Application - Swipe" instead of "Qt Quick Controls 2 Application" as that option wasn't available to me. Thanks in advance for any help.
Edit: I have written step by step instructions to replicate the issue below.
File > New File or Project
From the new window make sure "Application" is selected then click "Qt Quick Application - Swipe" and press "Choose"
Set any name for the project and click "Next"
Set the build system to "qmake" and click "Next"
Set the minimal required Qt version to "Qt 5.9" and the Qt quick controls style to "Material Dark" and click "Next"
Select the "Desktop Qt 5.12.0 MSVC2017 64bit" as the kit and click "Next"
Set the options to have no version control and click "Finish"
Delete "Page1Form.ui.qml" and "Page2Form.ui.qml" from the "Projects" pane
Replace the contents of "main.qml" with:
import QtQuick 2.9
import QtQuick.Controls 2.2
ApplicationWindow
{
visible: true;
width: 640;
height: 480;
title: qsTr("Tabs");
ToDoList
{
anchors.centerIn: parent;
}
}
Right click on the root project file and click "Add New"
From the new window make sure "Qt" is selected then click "QML File (Qt Quick 2)" and press "Choose"
Name the file "ToDoList" and click "Next"
Add to project "qml.qrc Prefix: /" then set the options to have no version control and click "Finish"
Replace the contents of "ToDoList.qml" with:
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
Frame
{
ListView
{
// Using implicit width and height allows the frame to automatically scale to the size of the list view
implicitWidth: 250
implicitHeight: 250
clip: true
model: 100
delegate: RowLayout {
width: parent.width
CheckBox {}
TextField
{
Layout.fillWidth: true
}
}
}
}
Run the project
The width is set properly. The problem is with TextField style. You may check it by setting background like
TextField
{
Layout.fillWidth: true
background: Rectangle {
color: "red"
}
}
Or just start typing into those fields with and without Layout.fillWidth: true

Material theme doesn't seem to work in QML

I have a simple QML with an ApplicationWindow, RowLayout and a bunch of Buttons inside. I have applied the Qt Quick Controls 2 Material theme as per the docs, but nothing changed. What's wrong?
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.3
ApplicationWindow {
Material.theme: Material.Dark
Material.accent: Material.Orange
id: window
visible: true
RowLayout {
anchors.horizontalCenter: window.horizontalCenter
anchors.bottomMargin: 32
Button {
text: "A"
}
Button {
text: "B"
}
Button {
text: "C"
}
}
}
Importing QtQuick.Controls.Material 2.0 and setting some Material specific properties do not apply the Material theme. They will be used if the theme is set using one of the methods described here:
http://doc.qt.io/qt-5/qtquickcontrols2-styles.html

Resources