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)
Related
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
}
}
How do I properly change the x, y of an object so that it changes its position when the parent is resized? There is, I will introduce that if I drag the rectangle to the middle, then when the window is resized, it should remain in the middle. (middle for example only, rectangle can be moved freely)
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.3
Window {
visible: true
width: 640
height: 480
onWidthChanged: {
block.x -= block.previousWidth - width
block.previousWidth = width
}
onHeightChanged: {
block.y -= block.previousHeight - height
block.previousHeight = height
}
Rectangle {
id: block
color: "red"
width: 50
height:50
x: 100
y: 50
property int previousWidth: 0
property int previousHeight:0
Component.onCompleted: {
previousWidth = parent.width
previousHeight = parent.height
}
MouseArea {
anchors.fill: parent
drag.target: block
}
}
}
I must admit, at first I was not impressed by the question. However, when I thought about it, it represents a very interesting and valid use case. So I would be happy to provide a solution.
Solution
I would approach the problem like this:
Make the frame a child of the background image.
Instead of manually calculating the coordinates, use Item.scale to scale the image, effectively preserving the relative position of the frame with regard to the image.
Example
Here is an example I have prepared for you to demonstrate how the proposed solution could be implemented:
import QtQuick 2.15
import QtQuick.Window 2.15
Window {
visible: true
width: 640
height: 480
Image {
anchors.centerIn: parent
source: "alphabet.png"
scale: parent.width/sourceSize.width
Rectangle {
id: frame
width: parent.width/7
height: parent.height/4
border.color: "black"
color: "transparent"
antialiasing: true
MouseArea {
anchors.fill: parent
drag.target: parent
}
}
}
}
Result
The example produces the following result:
Original window
Resized window
The frame is moved
The window is resized again
As I said in my comment, the best solution is anchoring, for example:
Window {
id: root
width: 600
height: 400
title: qsTr("Parent window")
visible: true
flags: Qt.WindowStaysOnTopHint
Grid {
anchors.fill: parent
Repeater {
model: 16
Rectangle {
width: root.width / 4
height: root.height / 4
color: Qt.rgba(Math.random(),Math.random(),Math.random(),1)
}
}
}
Rectangle {
border {
width: 5
color: "black"
}
color: "transparent"
width: root.width / 4
height: root.height / 4
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.leftMargin: root.width / 4
anchors.bottomMargin: root.height / 4
}
}
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..
Codes show as below:
import QtQuick 2.12
import QtGraphicalEffects 1.12
import QtQuick.Controls 2.12
Item {
width: 300
height: 300
TabBar {
id: bar
width: parent.width
contentHeight: 38
background: Rectangle {
color: "#477aa0"
}
TabButton {
id: tabBtn1
width: 129
height: 36
text: qsTr("Plate Layout")
anchors.top: parent.top
background: Rectangle {
color: "#ffffff"
}
}
//is tabBtn1's sibling!
DropShadow {
anchors.fill: tabBtn1
horizontalOffset: 3
verticalOffset: 4
radius: 5
samples: 11
color: "#000"
opacity: 0.75
source: tabBtn1
}
}
}
If TabBar change to Rectangle and TabButton change to Button, it works.As far as I know,qml included in brackets by Menu. I guess it is bug of Qt lib, maybe I am wrong.
This is because a DropShadow is not a TabButton, which causes this function to return false and it is not parented to the effective contentItem like the TabButton is. Note that the contentItem is a ListView, so making the DropShadow a child of it and trying to make it then fill the TabButton probably wouldn't work anyway.
An easier solution is to use layers:
TabButton {
id: tabBtn1
width: 129
height: 36
text: qsTr("Plate Layout")
anchors.top: parent.top
background: Rectangle {
color: "#ffffff"
}
layer.enabled: true
layer.effect: DropShadow {
anchors.fill: tabBtn1
horizontalOffset: 3
verticalOffset: 4
radius: 5
samples: 11
color: "#000"
opacity: 0.75
}
}
I have the following QML layout of the main application window. I need to create shadow for borderless window, that's why inner rectangle is a bit smaller than the application border (I found this solution on the StackOverflow before). The problem is when a new item is pushed to the nested StackView, it moves from the outside of the inner rectangle. How should I fix it?
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.2
import QtGraphicalEffects 1.0
import org.b2soft.qml 1.0
ApplicationWindow {
id: window
visible: true
width: 800
height: 600
title: qsTr("Test")
color: "#00000000"
flags: Qt.FramelessWindowHint | Qt.Window
Rectangle {
id: rect
width: 700
height: 500
anchors.centerIn: parent
Column {
id: column
anchors.fill: parent
Row {
id: topbar
anchors.left: parent.left
anchors.right: parent.right
height: 24
Rectangle {
anchors.top: parent.top
anchors.bottom: parent.bottom
width: parent.width
color: "#37373a"
}
}
StackView {
id: rootStackView
anchors.left: parent.left
anchors.right: parent.right
height: parent.height - topbar.height
initialItem: Qt.resolvedUrl("login.qml")
}
Connections {
target: QMLWrapper
onLoginCompleted: rootStackView.push(Qt.resolvedUrl("main_stack.qml"))
}
}
}
DropShadow {
anchors.fill: rect
radius: 40
samples: 32
verticalOffset: 14
source: rect
color: "#40000000"
}
}
Below is the GIF with the issue:
I'd go on a limb and assume that's the default intended behavior. QML elements do not clip by default, out of concern it might be a heavy operation.
And the stack view is usually contained inside the application window, so this issue would not be prominent.
But yours is nested into a smaller element, leaving room for the artifact to manifest.
All you have to do is set clip: true for rect.