Centering a group of QML widgets without changing their relative alignment - qt

The short version
I'd like to horizontally and/or vertically center groups of QML widgets without being forced to align them in a structured layout.
The long version
I made the following design:
My QML code so far is as follows. (I know the hardcoded X/Y coordinates are sloppy, it's just a mockup.)
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Shapes 1.11
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.0
Window {
id: window
visible: true
width: 640
height: 480
color: "#f0eded"
title: qsTr("Hello World")
Image {
id: image
x: 215
y: 96
sourceSize.height: 210
sourceSize.width: 210
source: "lock.svg"
}
Text {
id: element
y: 364
anchors.horizontalCenter: parent.horizontalCenter
color: "#646464"
text: qsTr("Unlock your rclone configuration to continue.")
anchors.horizontalCenterOffset: 0
styleColor: "#00000000"
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 12
}
TextField {
id: txtPassword
x: 193
y: 312
focus: true
font.pointSize: 22
horizontalAlignment: Text.AlignHCenter
echoMode: TextInput.Password
}
Button {
id: btnContinue
x: 399
y: 312
width: txtPassword.height
height: txtPassword.height
text: qsTr("»")
background: Rectangle {
border.color: btnContinueMouse.containsMouse ? "#cdcdcd" : "#ccc"
color: btnContinueMouse.containsMouse ? "#eee" : "#ddd"
}
MouseArea {
id: btnContinueMouse
anchors.fill: parent
hoverEnabled: true
}
}
}
What I'd like to do is to horizontally and vertically center this group of widgets so that its alignment still makes sense if a user increases the size of the window. I know I can put widgets into a row/column/grid layout for such purposes, but then I lose a lot of control over the space between the widgets.
What approach would you recommend to turn this mockup into clean QML code while staying true to the original design?

Two ways:
Wrap it in an Item, then
Use anchors to position your content relative to the screen like this:
Item {
anchors.fill: parent
Image {
id: image
anchors.left: parent.left
anchors.right: parent.right
sourceSize.height: 210
sourceSize.width: 210
source: "lock.svg"
}
Text {
id: element
anchors.top: txtPassword.bottom
anchors.left: txtPassword.left
anchors.right: btnContinue.right
color: "#646464"
text: qsTr("Unlock your rclone configuration to continue.")
styleColor: "#00000000"
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 12
}
OR
Create separate components out of the different parts then place them as a whole into a layout. Do this by moving your elements into a separate file then referencing that file using its name:
example:
LockElement { anchors.centerIn: parent }
will load LockElement.qml which will have your Item, Image, TextBox etc all in one file.
This will make the coordinates relative to their own coordinate space.
LockElement.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Shapes 1.11
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.0
Item {
width: 640
height: 480
Image {
id: image
x: 215
y: 96
sourceSize.height: 210
sourceSize.width: 210
source: "lock.svg"
}
Text {
id: element
y: 364
anchors.horizontalCenter: parent.horizontalCenter
color: "#646464"
text: qsTr("Unlock your rclone configuration to continue.")
anchors.horizontalCenterOffset: 0
styleColor: "#00000000"
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 12
}
TextField {
id: txtPassword
x: 193
y: 312
focus: true
font.pointSize: 22
horizontalAlignment: Text.AlignHCenter
echoMode: TextInput.Password
}
Button {
id: btnContinue
x: 399
y: 312
width: txtPassword.height
height: txtPassword.height
text: qsTr("»")
background: Rectangle {
border.color: btnContinueMouse.containsMouse ? "#cdcdcd" : "#ccc"
color: btnContinueMouse.containsMouse ? "#eee" : "#ddd"
}
MouseArea {
id: btnContinueMouse
anchors.fill: parent
hoverEnabled: true
}
}
}
// etc..

Related

QML scrollView scroll bar does not appear when text area overflows

here is what i did i have a text area inside a scrollview and a button at the bottom.
but when i try to overflow the text area by typing words so it will exceed the rectangle, the scrollbar does not appear, also when typing and pressing enter until the bottom of the Rectangle is reached, the vertical scrollbar does not appear as well.
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: 460
visible: true
title: qsTr("Edit Markdown source")
flags: Qt.WindowCloseButtonHint | Qt.CustomizeWindowHint | Qt.Dialog | Qt.WindowTitleHint
color: "red"
Column{
id: cols
anchors.fill: parent
anchors.margins: 5
spacing: 3
Rectangle {
id: frame2
width: parent.width
height: 400
border.color: 'gray'
border.width: 1
clip: true
color: "blue"
ScrollView {
id: view
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ScrollBar.horizontal.policy: ScrollBar.AsNeeded
TextArea {
text: ""
color: "white"
font.family: "Helvetica Neue"
font.pixelSize: 15
width: 10
height: 10
}
}
}
Rectangle{
id:saveRec
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 20
width: 80
height: 40
color: Qt.rgba(62/255,138/255,204/255,1)
radius: 4
Text{
anchors.centerIn: parent
text:"Save"
color:"white"
font.family: fontName
font.pixelSize: 15
}
MouseArea{
id:saveMouse
hoverEnabled:true
anchors.fill: parent
onEntered: {
saveRec.opacity = 0.5
}
onExited: {
saveRec.opacity = 1
}
onClicked:{
//...
}
}
}
}
}
All you're missing is that your ScrollView has no defined size. If you tell it how big it is, the scrollbars will get drawn. I'm not sure why you're setting the TextArea's height/width to be 10, but in my test it worked with or without those lines.
ScrollView {
id: view
anchors.fill: parent // Define the ScrollView's size
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ScrollBar.horizontal.policy: ScrollBar.AsNeeded
TextArea {
text: ""
color: "white"
font.family: "Helvetica Neue"
font.pixelSize: 15
// width: 10 // Not needed
// height: 10 // Not needed
}
}

Scroll Bar is not working in ScrollView qml

I'm trying to use a scrollbar inside a scrollview. The scrollbar shows up and I can interact with it (hover/pressed), but it doesn't move, and I can't understand why. I wrote my code by following the official documentation and online examples.
Here's the code:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtGraphicalEffects 1.15
Window {
width: 740
height: 580
visible: true
color: "#00000000"
title: qsTr("Hello World")
Rectangle {
id: rectangle
color: "#40405f"
anchors.fill: parent
Button {
id: button
text: qsTr("Menu")
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.leftMargin: 10
anchors.bottomMargin: 466
anchors.topMargin: 74
onClicked: animationMenu.running = true
}
ScrollView {
id: scrollView
width: 0
anchors.left: button.right
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.leftMargin: 10
anchors.bottomMargin: 10
anchors.topMargin: 10
clip: true
Rectangle {
id: rectangle1
color: "#00000000"
border.color: "#00000000"
border.width: 0
anchors.fill: parent
PropertyAnimation {
id: animationMenu
target: scrollView
property: "width"
to: if(scrollView.width == 0) return 240; else return 0
duration: 800
easing.type: Easing.InOutQuint
}
Column {
id: columnMenu
width: 0
anchors.fill: parent
spacing: 10
Button {
id: button1
text: qsTr("Button")
}
Button {
id: button2
text: qsTr("Button")
}
Button {
id: button3
text: qsTr("Button")
}
Button {
id: button4
text: qsTr("Button")
}
}
}
ScrollBar {
id: vbar
hoverEnabled: true
orientation: Qt.Vertical
size: scrollView.height / rectangle1.height
anchors.top: parent.top
anchors.right: parent.right
anchors.bottom: parent.bottom
wheelEnabled: true
pressed: true
active: true
}
}
}
}
Ok, so I edited the code to a smaller version so that it can be run.
Some advices:
Use anchors or Layouts. Do not use fixed values or some kind of treats, no matter if it works. The long term value of your code will be bad.
You should read carefully the (ScrollView documentatio). Also the Size section and the Touch and Mouse Interaction Section.
I am able to modify your example without the animation.
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.12
import QtGraphicalEffects 1.15
Window {
width: 740
height: 580
visible: true
color: "#00000000"
title: qsTr("Hello World")
Rectangle {
id: rectangle
color: "#40405f"
anchors.fill: parent
RowLayout{
anchors.fill: parent
Button {
id: button
text: qsTr("Menu")
width: 100
height: 50
}
ScrollView {
id: scrollView
Layout.fillWidth: true
Layout.fillHeight: true
RowLayout{
implicitHeight: 2000
implicitWidth: 2000
Column {
id: columnMenu
width: 0
anchors.fill: parent
spacing: 10
Repeater{
model: 50
delegate: Button {
text: qsTr("Button")
}
}
}
}
}
}
}
}

How to load and display QML file

I have two QML pages main.qml and Kos.qml,
what i want is when a button in main.qml clicked it load Kos.qml in the screen.
i did try using loader, but it is not working
import QtQuick 2.5
import QtQuick.Controls 2.5
ApplicationWindow {
id: applicationWindow
width: 640
height: 480
color: "#fc4343"
title: qsTr("Tabs")
visible: true
// HALAMAN UTAMA
Page {
anchors.centerIn: parent
anchors.fill: parent
id: page
enabled: true
Loader{
id: kos
active: true
anchors.fill: parent
}
Button {
id: button
x: 198
width: 87
height: 30
text: qsTr("Search")
font.bold: true
anchors.top: borderImage.bottom
anchors.topMargin: 198
anchors.right: toolSeparator.left
anchors.rightMargin: 28
MouseArea{
anchors.fill: parent
onClicked:{
kos.source = "Kos.qml";
}
}
background: Rectangle {
id: background
color: "#ef3644"
}
contentItem: Text {
id: textItem
font: control.font
opacity: enabled ? 1.0 : 0.3
color: "white"
text: "Search"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
}
}
Kos.qml i use PageBackground as a background
import QtQuick 2.4
PageBackground {
id: kos
width: 640
height: 480
Text {
id: element
x: 6
y: 20
width: 24
height: 32
color: "#ffffff"
text: qsTr("<")
font.strikeout: false
styleColor: "#ffffff"
font.underline: false
font.italic: false
font.bold: true
font.pixelSize: 25
MouseArea {
id: mouseArea
anchors.rightMargin: 0
anchors.bottomMargin: 0
anchors.leftMargin: 0
anchors.topMargin: 0
anchors.fill: parent
}
}
}
did i messed up somewhere?
I tried to run your code. Since I am not aware of what your PageBackground is, I changed that to Rectangle. That works for me. Try to start from the minimal code then add your styles and functions on top of it. Try with below minimal code. Keep both main.qml & Kos.qml in the same directory and ensure both files added to qml resources.
main.qml
import QtQuick 2.9
import QtQuick.Controls 2.2
ApplicationWindow {
id: applicationWindow
width: 640
height: 480
visible: true
Text {
anchors.centerIn: parent
text: "App window"
}
Loader {
id: loaderId
anchors.fill: parent
source: ""
}
Button {
text: "click me!!"
width: parent.width
anchors.bottom: parent.bottom
onClicked: {
if(loaderId.source == "")
loaderId.source = "Kos.qml"
else
loaderId.source = ""
}
}
}
Kos.qml
import QtQuick 2.9
Rectangle {
id: kos
width: 640
height: 480
color: "grey"
Text {
anchors.centerIn: parent
text: "<b>Loaded Item</b>"
color: "white"
}
}

Margins and anchors not working good in Qt, QML

I'm new at QML and I have a very confusing situation.
So, this is my main.qml file:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.0
Window {
id:rootWin
visible: true
width: 350
height: 330
ConnectBox
{
id:boxConnect
MouseArea
{
id: connectMouse
hoverEnabled: true
anchors.fill: boxConnect
}
}
Rectangle {
id: randomRec
width: parent.width/2
height: parent.height/6
// x: 50
anchors.top: boxConnect.bottom
// anchors.horizontalCenter: parent
anchors.topMargin: 10
border.color: "dimgray"
border.width: 5
radius: 14
}
}
ConnectBox.qml:
import QtQuick 2.0
Rectangle {
id: connectRec
width: parent.width/2
height: parent.height/6
anchors.centerIn: parent
border.color: "dimgray"
border.width: 5
radius: 14
}
I want it to be randomRec below boxConnect, so it does but it is all left and it only moves when I put for example x: 50 but its not convenient for every size of the window.
First off: I'd advise to put the anchors that are related to each other all on the same file.
But to get the randomRec to center below the connectBox you should use the following anchors:
Rectangle {
id: rect1
width: 100
height: 200
color: "red"
anchors.centerIn: parent
}
Rectangle {
id: rect2
width: 75
height: 50
color: "yellow"
anchors.top: rect1.bottom
anchors.horizontalCenter: rect1.horizontalCenter
}
So I guess you where almost there, with the horizontalCenter: parent line, which should have .horizontalCenter as well. However, I anchored it on rect1 since that is what you want (let's say you might want to move the boxConnect in the future... you would have to find all of the references)

How can I add the text on the top of the gridview in QML?

I am designing a layout in my program. I want to add a text on top of the gridview, but I just can make them overlap together. How can I add the text on top of the gridview? Thanks.
My code:
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtMultimedia 5.8
import QtQuick.Layouts 1.3
import com.contentplayermod.filemodel 1.0
import QtQuick.Window 2.2
ApplicationWindow {
id:main_win
visible: true
width: 640
height: 480
title: qsTr("Player")
property int idx: 0
property bool isActive: true
Row {
Text {
id:text1
anchors.bottom: grid_main.top
width: 240
height: 35
text: myModel.folder.toString()
font.family: "Helvetica"
font.pointSize: 20
color: "blue"
focus: true
}
}
GridView {
id:grid_main
anchors.fill: parent
anchors.top: text1.bottom
cellWidth: 100; cellHeight: 100
focus: true
currentIndex: 0
...
}
Your problem is that in the GridView you are setting the anchors in a conflictive way, on the one hand you indicate that it occupies the space of main_win, and on the other hand you indicate that the top anchor is the Text Item.
What you must do is that the GridView has as the top part the Text, and the other anchors are from the parent.
ApplicationWindow {
id:main_win
visible: true
width: 640
height: 480
title: qsTr("Player")
property int idx: 0
property bool isActive: true
Text {
id:text1
anchors.top: parent.top
width: 240
height: 35
text: myModel.folder.toString()
font.family: "Helvetica"
font.pointSize: 20
color: "blue"
focus: true
}
GridView {
id: grid_main
// annchors
anchors{
bottom: parent.bottom
right: parent.right
left: parent.left
top: text1.bottom
}
cellWidth: 100; cellHeight: 100
focus: true
currentIndex: 0
...
}

Resources