How can I make my GroupBox Layouts scalable in QML? - qt

I have the following problem. I created a Periodic table in QML that consists of GroupBoxes that contain a ColumnLayout in order to arrange the specific properties of each element. But as you can see in the pictures...
Window after starting
Window after downsizing
... the properties will not scale properly according to the size of the GroupBox. So when I scale down the size of the window, some text properties will just move out of its GroupBox and lay wherever they are not supposed to be. How can I fix this?
//PeriodicTable.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.15
import QtQuick.Layouts 1.15
Item {
id: root
Button {
id: button
checkable: true
text: qsTr("Show")
onClicked: window.show()
}
Window {
id: window
Material.accent: parent.Material.accent
Material.background: parent.Material.background
Material.foreground: parent.Material.foreground
Material.primary: parent.Material.primary
Material.theme: parent.Material.theme
color: Material.background
height: parent.height
title: qsTr("Periodic table")
width: parent.width
GridView {
id: gridview
anchors.fill: parent
cellHeight: cellWidth * 1.5
cellWidth: parent.width / 18
delegate: PeriodicTableDelegate {
}
model: PeriodicTableModel {
}
}
}
}
//PeriodicTableModel.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
ListModel {
id: elements
ListElement {
atomicWeight: "1.00794"
electronConfiguration: qsTr("1s")
elementName: qsTr("Hydrogen")
elementSign: qsTr("H")
ionizationEnergy: qsTr("13 5984")
ordinalNumber: qsTr("1")
unknownNumber: qsTr("S1/2")
}
} // I shortened this to just one element because yet it is the only one I have
// PeriodicTableDelegate.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
GroupBox {
property int cellHeight: GridView.view.cellHeight
property int cellWidth: GridView.view.cellWidth
height: cellHeight
width: cellWidth
ColumnLayout {
RowLayout {
Label {
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
font.bold: true
text: ordinalNumber
}
Label {
Layout.alignment: Qt.AlignRight
text: unknownNumber
}
}
Label {
Layout.alignment: Qt.AlignHCenter
font.bold: true
text: elementSign
}
Label {
Layout.alignment: Qt.AlignHCenter
text: elementName
}
Label {
Layout.alignment: Qt.AlignHCenter
text: atomicWeight
}
Label {
Layout.alignment: Qt.AlignHCenter
text: electronConfiguration
}
Label {
Layout.alignment: Qt.AlignHCenter
text: ionizationEnergy
}
}
}

a slightly contrived example:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Layouts 1.0
Window {
height: 800
width: 600
visible: true
title: qsTr("cell test")
GridView {
id: grid
anchors.fill: parent
cellHeight: grid.height / 3
cellWidth: grid.width / 4
model: 12
delegate: Rectangle {
id: rect
width: grid.cellWidth
height: grid.cellHeight
color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
ColumnLayout {
id: layout
anchors.fill: parent
Repeater {
model: 5
Text {
id: txt
property int fsize: (layout.height + layout.width) / 30
Layout.fillWidth: true
text: "some text"
horizontalAlignment:Text.AlignHCenter
font.pointSize: fsize > 0 ? fsize : 16
}
}
}
}
}
}

The ColumnLayout in your GroupBox is missing an anchors.fill: parent.

Related

Extra space at the bottom of Flow

I have a QML code like this:
MyItem.qml:
import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3
Item {
id: root
width: parent.width
height: grid.height
Rectangle {
anchors.fill: root
color: "blue"
z: -1
}
Flow {
id: grid
width: parent.width
spacing: 5
Button {
text: qsTr("Button 1")
}
Button {
text: qsTr("Button 2")
}
Button {
text: qsTr("Button 3")
}
}
}
main.qml:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ColumnLayout {
anchors.fill: parent
Button {
Layout.fillWidth: true
Layout.fillHeight: true
text: "hello"
}
MyItem {
Layout.fillWidth: true
}
}
}
If the Flow is wide enough for all three buttons to be at the same line (as with RowLayout) there is an extra empty space at the bottom of the Flow (approximately Button.height * 2). Looks like the Flow height is always calculated as the sum of all its element heights.
What is the logic behind this behavior? How to make the Flow fit its content height?
EDIT1: It is not Flow, but 'root' item has the wrong height.
EDIT2: Download the sample app
The problem with your code is that the root element the expressions:
anchors.fill: parent
height: grid.height
are competing, in the first expression you indicate that the dimensions of the root will take the size of the window and this implies the height but in the next expression you are indicating that the height will no longer be from the window but from the grid, so that generates an indefinite behavior. The only solution is to establish that the width of the root item is that of the window.
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Item {
id: root
height: grid.height
width: parent.width
Rectangle {
anchors.fill: root
color: "blue"
}
Flow {
id: grid
width: parent.width
spacing: 5
Button {
text: qsTr("Button 1")
}
Button {
text: qsTr("Button 2")
}
Button {
text: qsTr("Button 3")
}
}
}
}
Update:
It seems that you do not know how they work (read https://doc.qt.io/qt-5/qml-qtquick-layouts-layout.html#details), by default the height that is taken is the implicitHeight.
Also if you use layout you should not set anchors in the items that are directly affected by the layouts, in your case the CommandsTab is affected by the Layout so you should not use width: parent.width, is unnecesary.
CommandsTab.qml
import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3
Item {
id: root
implicitHeight: grid.height
Rectangle {
anchors.fill: root
color: "blue"
z: -1
}
Flow {
id: grid
width: parent.width
spacing: 5
Button {
text: qsTr("Button 1")
}
Button {
text: qsTr("Button 2")
}
Button {
text: qsTr("Button 3")
}
}
}
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ColumnLayout {
anchors.fill: parent
Button {
Layout.fillWidth: true
Layout.fillHeight: true
text: "hello"
}
CommandsTab {
Layout.fillWidth: true
}
}
}

Qt Quick layout changes on different events

When I execute my QML code, the output is:
When I minimize the window, It becomes like
and finally, when I again maximize the window it changes to
the GUI which I want to make looks like
![][5]
I am not getting what is the issue for all of the changes in GUI at different events. And this is the Qml code which I wrote
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3
Window {
visible: true
width: 1080
height: 720
title: qsTr("Login")
GridLayout{
Rectangle{
id:one
Rectangle
{ id:two
color:"black";
width: 700
height:40
}
Image {
id: image
x: 470
y: 0
width: 54
height: 42
source: "qrc:/user.png"
}
Rectangle
{
id:three;
color:"#f47a42";
width: 200
height:40
anchors.left:two.right;
anchors.margins:940
Text {
id: user
text: qsTr("4200")
color:"white"
anchors.top: value.bottom
}
Text
{
id: value;
text: qsTr("User");
color:"yellow"
}}
}
}
Rectangle{
ColumnLayout{
width: 50
height: childrenRect.height+fillHeight;
}
color:"green"
}
}
So why this is happening and how can I solve this problem?
Output of the code below
Here is example of scalable window:
import QtQuick 2.11
import QtQuick.Window 2.11
import QtQuick.Layouts 1.11
Window {
visible: true
width: 800
height: 600
title: qsTr("Layout example")
ColumnLayout{
spacing: 0
anchors.fill: parent
Item {
id: titlebar
Layout.preferredHeight: 40
Layout.fillWidth: true
RowLayout {
anchors.fill: parent
spacing: 0
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "orange"
Text {
anchors.centerIn: parent
text: "Title"
}
}
Rectangle {
Layout.preferredWidth: 100
Layout.fillHeight: true
color: "lightgreen"
Text {
anchors.centerIn: parent
text: "Actions"
}
}
}
}
Rectangle {
id: content
Layout.fillHeight: true
Layout.fillWidth: true
color: "lightyellow"
Text {
anchors.centerIn: parent
text: "Content"
}
}
}
}

Issue with toolbar layout, each tab is stacking on top of each other

I'm trying to get a tool bar working but the first 3 tab buttons keep writing on top of each other.
Each tab gets display on top of one another on the left hand side of the screen.
I would like each tab button to fill and take up its on unique space.
How do I get the toolbar to display 3 individual tabs that span horizontally across the screen at equal size?
import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.1
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls.Material 2.1
import QtGraphicalEffects 1.0
import "../controls" as Controls
Page{
anchors.fill: parent
header: ToolBar{
Material.background: "green"
TabButton {
id: tab1
width: parent.width/3
text: qsTr("Asset")
Image{
source: "../assets/clipboard.png"
}
onClicked: qmlfile1 = "./asset.qml"
}
TabButton {
id:tab2
width: parent.width/3
text: qsTr("Issue")
Image{
source: "../assets/wrench.png"
}
onClicked: qmlfile1 = "./issue.qml"
}
TabButton {
width: parent.width/3
id: tab3
text: qsTr("Log")
Image{
source: "../assets/cogs.png"
}
onClicked: qmlfile1 = "./log.qml"
}
}
Rectangle{
id: loader1
Loader{
width: pageApp.width
source: qmlfile1
}
Component.onCompleted: {
console.log(loader1.height)
console.log(pageApp.height)
console.log(tabBarApp.height)
}
}
}
The solution was to add row layout and each tab button gets
Layout.fillHeight: true
Layout.fillWidth: true
which fills the tabs out to occupy all space it needs
import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.1
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls.Material 2.1
import QtGraphicalEffects 1.0
import "../controls" as Controls
Page{
anchors.fill: parent
header: ToolBar{
Material.background: "green"
RowLayout {
anchors.fill: parent
TabButton {
id: tab1
width: parent.width/3
text: qsTr("Asset")
Layout.fillHeight: true
Layout.fillWidth: true
Image{
source: "../assets/clipboard.png"
Layout.alignment: Qt.AlignLeft
}
onClicked: qmlfile1 = "./asset.qml"
}
TabButton {
id:tab2
width: parent.width/3
Layout.fillHeight: true
Layout.fillWidth: true
text: qsTr("Issue")
Image{
source: "../assets/wrench.png"
Layout.alignment: Qt.AlignLeft
}
onClicked: qmlfile1 = "./issue.qml"
}
TabButton {
width: parent.width/3
Layout.fillHeight: true
Layout.fillWidth: true
id: tab3
text: qsTr("Log")
Image{
source: "../assets/cogs.png"
Layout.alignment: Qt.AlignLeft
}
onClicked: qmlfile1 = "./log.qml"
}
}
}
// Add a Loader to load different samples.
// The sample Qml files can be found in the Samples folder
Rectangle{
id: loader1
Loader{
width: pageApp.width
source: qmlfile1
}
Component.onCompleted: {
console.log(loader1.height)
console.log(pageApp.height)
console.log(tabBarApp.height)
}
}
}

center a checkbox in tableview with QML

I am using a checkbox control in a TableView, which I define with QML as follows:
import QtQuick 2.2
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
TableViewColumn {
title: ""
role: "check"
delegate: CheckBox {
anchors.fill: parent
checked: false
anchors { horizontalCenter: parent.horizontalCenter }
}
}
I can use it in a TableView as follows:
import QtQuick 2.3
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
ControlView {
visible: true
width: parent.width; height: parent.height
anchors.centerIn: parent
TableView {
id: reviewTable
width: parent.width; height: parent.height
anchors.centerIn: parent
TableViewCheckBoxColumn {
title: "Upload"
width: 100
resizable: false
}
TableViewColumn {
resizable: true
role: "Dummy"
title: "Dummy"
width: 250
}
style: TableViewStyle {
headerDelegate: Rectangle {
height: textItem.implicitHeight
width: textItem.implicitWidth
Text {
id: textItem
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
text: styleData.value
renderType: Text.NativeRendering
font.bold: true
}
}
}
model: ListModel {
ListElement {
Dummy: "value 1"
}
ListElement {
Dummy: "value 3"
}
}
}
}
Now despite having set the anchors (or any alignment property that were available), the checkbox remains aligned to the left. How can I center it horizontally wrt to the column?
Wrap the CheckBox in the delegate as below:
Item {
anchors.fill: parent
CheckBox {
anchors.centerIn: parent
checked: false
}
}
And btw, don't mix QtQuick versions in the same application.

Even width of Text and Textfield

I have a simple login form written in QML with a custom component, MediumText, and two TextFields. Unfortunately, I'm not able to properly align the elements, as shown by the following picture:
I want the labels to the left (MediumText type), as well as the TextField instances on the right, to take up the same amount of space so that they are correctly aligned. Can you suggest me an approach? Here is my current code.
MediumText.qml:
import QtQuick 2.3
Text {
clip: true
font.pixelSize: 20
font.family: "Liberation Mono"
smooth: true
font.bold: true
wrapMode: Text.WordWrap
opacity: 1
}
Login.qml:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
Rectangle {
id:rootRect
anchors.centerIn: parent
Layout.preferredWidth: 480
Layout.preferredHeight: 640
ColumnLayout {
anchors.centerIn: parent
Layout.fillWidth: true
spacing: 16
Row{
Image {
id: logoimage
height: 135
fillMode: Image.PreserveAspectFit
source: "images/logo.png"
}
}
RowLayout {
anchors.left: parent.left; anchors.right: parent.right
spacing: 4
MediumText { text: "Username: ";Layout.fillWidth:true; }
TextField { id:usernameText; placeholderText: "username"; Layout.fillWidth: true;}
}
RowLayout {
anchors.left: parent.left; anchors.right: parent.right
spacing: 4
MediumText { text: "Password:";Layout.fillWidth:true }
TextField { id:passwordText; placeholderText: "password"; echoMode: TextInput.Password; Layout.fillWidth: true;}
}
RowLayout {
spacing: 16
anchors.horizontalCenter: parent.horizontalCenter
Button { text: "Login"; onClicked: {
console.log(mojoLoginLoader.visible);
mojoLoginLoader.visible=true;
passwordText.enabled=false;
usernameText.enabled=false;
//auth_controller.sayHello();
mojoRootViewHolder.source="Welcome.qml"
}
}
Button { text: "Exit"; onClicked: auth_controller.sayNay() }
}
}
CenteredLoader{visible:false; id:mojoLoginLoader}
}
One fix that works is setting the preferredWidth property of the TextField:
MediumText { text: "Username: ";Layout.fillWidth:true;Layout.preferredWidth: parent.width/2}
You can use a GridLayout instead of building a grid by means of ColumnLayout and RowLayout.
By using the GridLayout, what you want is already guaranteed by the component.
Here is a full example from which you can start:
import QtQuick 2.3
import QtQuick.Window 2.2
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
Window {
visible: true
width: 500
height: 500
title: "Grid example"
ColumnLayout {
anchors.centerIn: parent
Layout.fillWidth: true
spacing: 16
Row{
Image {
id: logoimage
height: 135
fillMode: Image.PreserveAspectFit
source: "images/logo.png"
}
}
GridLayout {
anchors.centerIn: parent
Layout.fillWidth: true
columnSpacing: 16
rowSpacing: 4
columns: 2
MediumText { text: "Username: "; Layout.fillWidth:true; }
TextField { id:usernameText; placeholderText: "username"; Layout.fillWidth: true;}
MediumText { text: "Password:";Layout.fillWidth:true }
TextField { id:passwordText; placeholderText: "password"; echoMode: TextInput.Password; Layout.fillWidth: true;}
}
RowLayout {
spacing: 16
anchors.horizontalCenter: parent.horizontalCenter
Button { text: "Login"; onClicked: {
console.log(mojoLoginLoader.visible);
mojoLoginLoader.visible=true;
passwordText.enabled=false;
usernameText.enabled=false;
//auth_controller.sayHello();
mojoRootViewHolder.source="Welcome.qml"
}
}
Button { text: "Exit"; onClicked: auth_controller.sayNay() }
}
}
}

Resources