I have a Button which text changes and when its text changes, its width also changes. I want to animate this change in width when I change the text. How can I do that ?
I tried following but its not working
import QtQuick.Window 2.15
import QtQuick 2.15
import QtQuick.Controls 2.15
Window {
width: 500
height: 600
visible: true
Button {
property bool t: false
text : t ? "very more text hahaha haha hehe" : "less text"
onClicked: t = !t
Behavior on width {
NumberAnimation {
duration: 1000
}
}
}
}
The change of the Button width is a byproduct of its implicitWidth being changed here.
By changing the Behavior to trigger on implicitWidth instead of width you will have your expected behavior.
Related
I want to to scale a button's text with respect to its height:
import QtQuick 2.11
import QtQuick.Controls 2.10
ToolButton {
id: btn
font.pixelSize: implicitHeight*0.8 // Binding loop detected for property "font.pixelSize"
contentItem: Text {
text: btn.text
font: btn.font
}
}
This sometimes works but more often a binding loop is detected because when the font size changes, also the button size changes. What is the correct way for scaling the text size?
Regards,
Use "height" instead of "implicitHeight".
And the ToolButton's height is bound to the font size by default, so you need to set a height for your button.
One method to avoid the binding loop is not use declarative code but imperative instead. For this, we watch for onWidthChanged and onHeightChanged and invoke resize(). Our resize routine we compute a scale using a fixed TextMetric at a reference font size. With that we can size the text accordingly:
import QtQuick 2.15
import QtQuick.Controls 2.15
Page {
anchors.fill: parent
ToolButton {
id: btn
anchors.centerIn: parent
width: parent.width / 2
height: parent.height / 2
text: qsTr("Hello")
property TextMetrics tm: TextMetrics {
font.pixelSize: 20
text: btn.text
}
onWidthChanged: Qt.callLater(resize)
onHeightChanged: Qt.callLater(resize)
function resize() {
let fx = width / tm.width * tm.font.pixelSize * 0.8;
let fy = height / tm.height * tm.font.pixelSize * 0.8;
font.pixelSize = Math.min(fx, fy)
}
}
}
You can Try it Online!
I'm trying to make two group boxes appear next to each other so that each one occupies 50% of the window. However, it looks like the width of each GroupBox is somehow changed depending on the GroupBox title length.
If the GroupBox title is the same for both GroupBox's, it will be 50% of the window. If they are not the same, the GroupBox with the longer title will occupy more of the screen.
It doesn't make sense to me for this to happen, how can I fix it so the length of the title doesn't effect the size of the GroupBox in a layout?
Here's sample code to reproduce the issue...
AppGroupBox.qml
import QtQuick 2.0
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.12
GroupBox {
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
spacing:0
label.x: 0
}
AppRowLayout.qml
import QtQuick 2.0
import QtQuick.Layouts 1.12
RowLayout {
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
spacing: 0
}
main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
Window {
width: 640
height: 480
visible: true
AppRowLayout {
anchors.fill: parent
AppGroupBox {
title: "Short Name"
Layout.fillWidth: true
}
AppGroupBox {
title: "Much Longer Name"
Layout.fillWidth: true
}
}
}
Qt will distribute the free space relative to the Layout.preferredWidth (or implicitWidth if that isn't defined). So, a group box with a longer title will get more space by default, as its implicitWidth is larger.
The solution is to use a fixed preferredWidth for all elements in the RowLayout:
GroupBox {
...
Layout.preferredWidth: 50 // or any other fixed value.
Layout.minimumWidth: implicitWidth // OPTIONAL: may be usefull on small screens to ensure the box is not made smaller than the title width
...
}
Note on attached properties:
Layout.alignment is an attached property available on the children of a Layout (RowLayout, GridLayout or ColumnLayout). Setting it directly inside a RowLayout object is useless (except when the RowLayout itself is a child of another Layout item.
I am trying to create a simple window in QML with a huge text area in the center and a couple of buttons at the bottom,
bellow is the code
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
Window {
id: mainWindow
width: 500
height: 300
visible: true
title: qsTr("Hello World")
flags: Qt.WindowCloseButtonHint | Qt.CustomizeWindowHint | Qt.Dialog | Qt.WindowTitleHint
ColumnLayout{
anchors.fill: parent
anchors.margins: 5
RowLayout {
Layout.alignment: Qt.AlignTop
TextArea {
text: "Hello world!"
}
}
RowLayout {
Layout.alignment: Qt.AlignBottom | Qt.AlignRight
Button {
text: "Ok"
}
Button {
text: "Cancel"
}
}
}
}
however when i press enter key multiple times enough to reach almost at the bottom of the text area, the button moves because the text area resizes, how do I prevent this?
How do I set the text area so that it doesnt resize and push the buttons out of the window, but still be responsive that if the window resize it maintains its positions like buttons will still be buttom right and text area adjusts based on anchor.
It sounds like you want your TextArea to fill the space above the buttons, but your present code is not doing this. If I add a transparent red Rectangle to fill your TextArea, you can see what is happening:
The reason for this is that, by default, the TextArea is only as large as its text (implicitHeight/implicitWidth). Instead, if you want it to fill the top area, you need to specify Layout.fillHeight and Layout.fillWidth. This also means you maybe shouldn't have to rely on Layout.Alignment. Here is your code updated with these fills specified and some alignment properties removed:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
Window {
id: mainWindow
width: 500
height: 300
visible: true
title: qsTr("Hello World")
flags: Qt.WindowCloseButtonHint | Qt.CustomizeWindowHint | Qt.Dialog | Qt.WindowTitleHint
ColumnLayout{
anchors.fill: parent
anchors.margins: 5
RowLayout {
TextArea {
text: "Hello world!"
Layout.fillHeight: true
Layout.fillWidth: true
}
}
RowLayout {
Layout.alignment: Qt.AlignRight
Button {
text: "Ok"
}
Button {
text: "Cancel"
}
}
}
}
You can see the result if we add another transparent colored Rectangle to make it visually clear what is happening:
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
}
}
I would like to set the minimum width and height of my QML Application window, so that the content item is fully visible (not clipped).
import QtQuick 2.5
import QtQuick.Controls 1.4
ApplicationWindow {
visible: true
width: 100
height: 100
title: "test"
minimumWidth: circle.width
minimumHeight: circle.height // + menuBar.height
menuBar: MenuBar {
Menu {
title: qsTr("File")
MenuItem {
text: qsTr("Exit")
onTriggered: Qt.quit();
}
}
}
Rectangle {
id: circle
anchors.centerIn: parent
width: 200
height: 200
color: "red"
radius: width * 0.5
}
}
Here is the result:
As you can see, setting the minimum width works fine. The minimum height seems to be off by the height of the menu bar. The problem is, adding something like menuBar.height does not work as this property does not exist.
So the question is: how do I set the size of the ApplicationWindow, so that the content item (given by width/height or implicitWidth/implicitHeight) is not clipped?
Note: In reality, instead of a red circle, the content item serves as a game canvas, which I would like to resize dynamically.
As always with the old QtQuick.Controls 1.x the only way to help yourself is, to look at the (undocumented/internal) properties. For the MenuBar those are:
objectName
menus
__contentItem
__parentWindow
__isNative
style
__style
__menuBarComponent
objectNameChanged
menusChanged
nativeChanged
contentItemChanged
styleChanged
__styleChanged
__menuBarComponentChanged
__contentItem seems to be interesting, and it features a height - as soon as it is instantiated.
So we can define the height of the ApplicationWindow as such:
minimumHeight: contentItem.childrenRect.height
+ (menuBar.__contentItem ? menuBar.__contentItem.height : 0)