QML custom layout - qt

I am using QML to display a background image and this image needs to be overlaid by icons. Each of these items is attached a MouseArea so the icons are actually used as buttons.
Now the icons need to scale and move together with the background image. Their layout behavior need to be such that the icons look as if they were part of the background image (I did not include the icons into the background image because the icons are "active" and are associated the MouseArea).
The behavior I get is that the icons scale well with the background image (when the image is resized, the icons are rescaled accordingly) which is great. Now unfortunately the position x / y of the icons is not correct, I do not manage the find the formula for x /y such that the icons are moved together with the background resize and give the feeling that the icon are part of the background image.
Here is my current code:
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.3
Rectangle
{
color: palette.grey
// Manual move background and buttons.
Image
{
id: robotBody
fillMode: Image.PreserveAspectFit
anchors.top: parent.top
anchors.topMargin: 10
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width
height: parent.height * 0.8
source: "../UI/Pictures/ManualMove_body.png"
smooth: true
// Buttons.
Image
{
id: xFrontButton
fillMode: Image.PreserveAspectFit
source: "../UI/Icons/ManualMove_XFront.png"
smooth: true
x: 0.8 * parent.paintedWidth
y: 0.8 * parent.paintedHeight
transformOrigin: Item.TopLeft
width: implicitWidth * robotBody.paintedWidth / robotBody.implicitWidth
// NOTE: no need to specify the height because of the preserve aspect ratio fill mode.
MouseArea
{
id: xFrontMouseArea
anchors.fill: parent
hoverEnabled: true
onPressed: { uiController.onXFrontMouseAreaPressed() }
onReleased: { uiController.onXFrontMouseAreaReleased() }
}
}
}
}
Any idea of what is going wrong?
Thanks,
Antoine.

Don't forget this moment:
x: (parent.width - parent.paintedWidth)/2 + 0.8 * parent.paintedWidth
y: (parent.height - parent.paintedHeight)/2 + 0.8 * parent.paintedHeight
I.e. do this:
import QtQuick 2.0
//import QtQuick.Controls 2.0
//import QtQuick.Controls.Styles 1.4
//import QtQuick.Controls.Material 2.0
//import QtQuick.Layouts 1.3
Rectangle
{
// color: palette.grey
color: "grey"
// Manual move background and buttons.
Image
{
id: robotBody
fillMode: Image.PreserveAspectFit
anchors.top: parent.top
anchors.topMargin: 10
// anchors.horizontalCenter: parent.horizontalCenter
width: parent.width
height: parent.height * 0.8
// source: "../UI/Pictures/ManualMove_body.png"
source: "Large.png"
smooth: true
// Buttons.
Image
{
id: xFrontButton
fillMode: Image.PreserveAspectFit
// source: "../UI/Icons/ManualMove_XFront.png"
source: "small.png"
smooth: true
x: (parent.width - parent.paintedWidth)/2 + 0.8 * parent.paintedWidth
y: (parent.height - parent.paintedHeight)/2 + 0.8 * parent.paintedHeight
// transformOrigin: Item.TopLeft
width: implicitWidth * robotBody.paintedWidth / robotBody.implicitWidth
// NOTE: no need to specify the height because of the preserve aspect ratio fill mode.
MouseArea
{
id: xFrontMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: console.log("Heya!")
// onPressed: { uiController.onXFrontMouseAreaPressed() }
// onReleased: { uiController.onXFrontMouseAreaReleased() }
}
}
}
}
Cheers from Russia :)

Related

QML DropShadow sometimes renders badly

I am using QML's inbuilt DropShadow type (import QtGraphicalEffects) to generate a shadow of some rectangles that are contained within an Item. The DropShadow is also a child of said Item. But sometimes the shadow is rendered very badly. I am dynamically creating the screen and adding it to a SwipeView; the code is as follows:
swipeView.addItem(tasksScreen.createObject(swipeView))
swipeView.incrementCurrentIndex()
"tasksScreen" is the screen that the rectangles and DropShadow are part of.
The following video depicts the issue and the code that generates this behavior:
https://yadi.sk/i/mwl_8IZmm_jetQ
I believe the issue is you are making the DropShadow a child of its source - which is creating a looping dependency.
Instead, try making it a sibling of your Item or even better, set it up as your Item's layer.effect.
You can see these different techniques in the DropShadow documentation:
https://doc.qt.io/qt-5/qml-qtgraphicaleffects-dropshadow.html
The problem is the source property in your code you have set the source as the parent item in your code. Give the source as your visual object(Rectangle). I have attached the code for your reference.
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
import QtGraphicalEffects 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Component {
id: swipeviewComponentId
Item {
id: itemId
Rectangle {
id: rectangleId
anchors.fill: parent
anchors.margins: 10
radius: 10
}
DropShadow {
anchors.fill: source
horizontalOffset: 3
verticalOffset: 3
radius: 8.0
samples: 17
color: "#80000000"
source: rectangleId
}
}
}
Column {
anchors.fill: parent
anchors.margins: 10
spacing: 10
SwipeView {
id: swipeViewId
width: parent.width
height: parent.height - addButtonId.height - (2 * parent.spacing) - pageIndicatorId.height
}
PageIndicator {
id: pageIndicatorId
currentIndex: swipeViewId.currentIndex
count: swipeViewId.count
anchors.horizontalCenter: parent.horizontalCenter
}
Button {
id: addButtonId
width: parent.width
height: 40
text: "Add item"
onClicked: {
swipeViewId.addItem(swipeviewComponentId.createObject(swipeViewId,
{height: swipeViewId.height, width: swipeViewId.width}))
swipeViewId.incrementCurrentIndex()
}
}
}
}

QML: Buttons become transparet over images using Material Style

I want my application to use an image as a Background. So I use this code:
In my ApplicationWindow:
Image {
id: bkgImage
source: "qrc:/images/bkg.jpg"
anchors.centerIn: parent
}
To add a button
Button {
id: btnAsistencia
text: qsTr("ASISTENCIA")
font.pixelSize: fhButttonTextSize
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: btnInscripcion.bottom
anchors.topMargin: parent.height*0.1
}
The code above is for the second button, but I added one before in the exact same way. This is the result:
The second button becomes transparent over the image. How can I prevent this?
You can set the background colour of the button with the Material.background attached property:
import QtQuick 2.0
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
ApplicationWindow {
id: window
width: 400
height: 440
visible: true
color: "red"
Button {
text: qsTr("ASISTENCIA")
Material.background: "#666"
}
}
The default colour has some transparency:
http://code.qt.io/cgit/qt/qtquickcontrols2.git/tree/src/imports/controls/material/qquickmaterialstyle.cpp#n862

Move Flickable/ListView using Slider QML

I need to scroll a Flickable/ListView using a Slider rather than a scrollbar, If I use a ScrollBar everything works perfect but I need a visual experience like a slider(A round handle and a path line). As In vertical scrollBar we can't set height of the handle and in the horizontal scrollbar, we can't set width of the handle. Due to this limitation, I used the slider itself to scroll a Flickable/ListView. Following is the code:
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
Window {
id:window
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Flickable{
id:flick
width : parent.width * 0.70
height : parent.height * 0.70
contentWidth: contentItem.childrenRect.width
contentHeight: contentItem.childrenRect.height
contentX:(contentWidth - width) * horSlider.position
contentY:(contentHeight-height) * verSlider.position
clip:true
Grid{
id:grid
columns: 5
spacing:50
Repeater{
id:rept
model:20
Button{
width: 100
height : 100
text:"Btn "+index
}
}
}
}
Slider{
id:horSlider
anchors.top:flick.bottom
anchors.left:flick.left
anchors.right:flick.right
}
Slider{
id:verSlider
orientation: Qt.Vertical
anchors.top:flick.top
anchors.bottom:flick.bottom
anchors.left:flick.right
rotation: 180
}
}
1) If I move the sliders Flickable is moving as expected but if Interactive flag is enabled then how to move the sliders if user flicks with the fingers rather than using sliders?
2) Is there any way to design a scrollBar similar to Slider (A round handle with a path Line)?
Here's an example how to connect Flickable and Sliders together. Notice that vertical slider's handle is at the bottom when the position is 0, so you need to invert the position.
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 2.0
Window {
id: window
width: 360
height: 360
visible: true
Flickable {
id: flickable
anchors.fill: parent
contentWidth: dummyContent.width
contentHeight: dummyContent.height
Text {
id: dummyContent
text: "ABC"
color: "red"
font.pixelSize: 512
}
}
Slider {
id: hslider
anchors.left: parent.left
anchors.right: vslider.left
anchors.bottom: parent.bottom
value: flickable.contentX / (flickable.contentWidth - flickable.width)
Binding {
target: flickable
property: "contentX"
value: hslider.position * (flickable.contentWidth - flickable.width)
when: hslider.pressed
}
}
Slider {
id: vslider
orientation: Qt.Vertical
anchors.top: parent.top
anchors.right: parent.right
anchors.bottom: hslider.top
value: 1.0 - (flickable.contentY / (flickable.contentHeight - flickable.height))
Binding {
target: flickable
property: "contentY"
value: (1.0 - vslider.position) * (flickable.contentHeight - flickable.height)
when: vslider.pressed
}
}
}

QML: QtQuick.Controls Tabs with Icons

I have been learning how to use QT Creator Tool so that I can build UI's quickly and easily. For my current project, I have to use QML to build my UI. I want to have tabs in my display. I would like to use an image in place of text in my tab. My code is below. I have tried to add a source but that did not help me add an icon. Does anyone know how to do this? All help would be greatly appreciated.
import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Controls 1.0
import QtQuick.Controls.Styles 1.2
Window {
visible: true
width: 640
height: 400
opacity: 1
TabView {
height: 300
anchors.rightMargin: 0
anchors.bottomMargin: 0
anchors.leftMargin: 0
anchors.topMargin: 0
anchors.fill: parent
Tab {
title: "Robot"
component: Qt.createComponent("RobotControls.qml")
}
Tab{
title: "Tab #2"
}
}
}
Elaborating on the answer from Simon Warta in Extending TabViewStyle styleData, here is what you could do :
Define a custom IconTab
You want to extend the Tab item so that you can specify an icon to display.
So add a new file to your project, called IconTab.qml:
IconTab.qml
import QtQuick.Controls 1.4
Tab{
property string icon
}
Define a custom TabViewStyle.
In order to use this new property, you must create your own TabViewStyle. You may have to redefine background and text size and colors so that it fits your app theme, but something like this could work:
MyStyle.qml
import QtQuick 2.5
import QtQuick.Controls.Styles 1.2
TabViewStyle {
tab: Item {
implicitWidth: Math.round(textitem.implicitWidth + image.width + 20)
implicitHeight: Math.round(textitem.implicitHeight + 10)
Rectangle
{
anchors.fill: parent
anchors.bottomMargin: 2
radius: 1
border.width: 1
border.color: "#AAA"
color:"transparent"
}
Rectangle
{
anchors.fill: parent
anchors.margins: 1
anchors.bottomMargin: styleData.selected ? 0 : 2
radius: 1
gradient: Gradient{
GradientStop{position:0; color:styleData.selected?"#EDEDED":"#E3E3E3"}
GradientStop{position:1; color:styleData.selected?"#DCDCDC":"#D3D3D3"}
}
}
Text {
id: textitem
anchors.fill: parent
anchors.leftMargin: 4 + image.width
anchors.rightMargin: 4
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: styleData.title
elide: Text.ElideMiddle
}
Image
{
id: image
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.margins: 2
anchors.leftMargin: 4
fillMode: Image.PreserveAspectFit
source: control.getTab(styleData.index).icon
}
}
}
Note how you can make use of the control property and the styleData.index to get your icon's url: control.getTab(styleData.index).icon
Put the pieces together
main.qml
import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Controls 1.0
Window {
visible: true
width: 640
height: 400
TabView {
id: tabView
anchors.fill: parent
style: MyStyle{}
IconTab {
title: "Tab #1"
icon: "icon.png"
}
IconTab{
title: "Tab #2"
}
IconTab{
title: "Tab #3"
icon: "icon.png"
}
}
}
Result

Shadow for qml frameless windows

I have frameless main window, created by qml ( ApplicationWindow {..} in my main.qml file)
I instantiate qml by QQmlApplicationEngine::load (class introduced in Qt5.1).
If I set the Qt.FramelessWindowHint flag, the window is frameless, but loses shadow (in Windows).
How to add shadow to my window?
My window listing:
ApplicationWindow {
id: rootWindow
color : "#f8f8f8"
maximumHeight: 445
minimumHeight: 445
minimumWidth: 730
maximumWidth: 730
flags : Qt.FramelessWindowHint | Qt.Window
Component.onCompleted: {
setHeight(455)
setWidth(740)
}
MainObject{
id:mainObject1
anchors.fill: parent
height:445
width:730
}
}
The solution is to implement the shadow part integral to the application, this way you can disable WM decoration and still have decoration, and have it consistent across different platforms.
In the following example the window has a shadow that even animates to create the effect of lifting the window up when moving it. And when the window is maximized, the margins are removed and the shadow is thus no longer visible.
import QtQuick 2.7
import QtQuick.Controls 2.1
import QtGraphicalEffects 1.0
import QtQuick.Window 2.3
ApplicationWindow {
id: main
visible: true
width: 300
height: 200
color: "#00000000"
flags: Qt.FramelessWindowHint | Qt.Window
Rectangle {
id: rect
anchors.fill: parent
anchors.margins: main.visibility === Window.FullScreen ? 0 : 10
MouseArea {
id: ma
anchors.fill: parent
property int dx
property int dy
onPressed: { dx = mouseX; dy = mouseY }
onPositionChanged: {
main.x += mouseX - dx
main.y += mouseY - dy
}
onDoubleClicked: main.visibility = main.visibility === Window.FullScreen ? Window.AutomaticVisibility : Window.FullScreen
}
}
DropShadow {
anchors.fill: rect
horizontalOffset: 1
verticalOffset: 1
radius: ma.pressed ? 8 : 5
samples: 10
source: rect
color: "black"
Behavior on radius { PropertyAnimation { duration: 100 } }
}
}
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtGraphicalEffects 1.0
ApplicationWindow{
id: window
visible: true
width: 640
height: 480
title: qsTr("Hello World")
flags: Qt.Window | Qt.FramelessWindowHint
color: "#00000000"
Rectangle {
id: rect
anchors.fill: parent
anchors.margins: 10
radius: 5
}
DropShadow {
anchors.fill: rect
samples: 20
source: rect
color: "gray"
}
}
If you mean the drop shadow effect, that is not quite so.
We have no control over the WM decoration in Qt besides the frameless window flag you have just used. It is pretty much WM specific. Windows (TM) WM applies shadow effect to decorate windows, but this is a Windows (TM) choice. Also, you have just hinted that it should not decorate.

Resources