Shadow for qml frameless windows - qt

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.

Related

Display Rectangle outside of parent or Window [duplicate]

I need to have a Popup that stays visible outside the bounds of the main window.
I couldn't find anything in the Qt documentation.
This is the code:
import QtQuick 2.15
import QtQuick.Window 2.2
import QtQuick.Controls 2.12
ApplicationWindow {
id: window
width: 400
height: 400
visible: true
Button {
text: "Open"
onClicked: popup.open()
}
Popup {
id: popup
x: 100
y: 100
width: 300
height: 400
modal: true
focus: true
dim: false
contentItem: Rectangle
{
anchors.fill: parent
color: "red"
}
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
}
}
This is the output of this:
I want the red to go beyond the window borders.
Something like this:
I'd appreciate the help!
Note: using a Dialog is no good for me.
Popups are not proper windows, so you'd need to create a new window like Michael mentioned:
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
id: mainWindow
width: 640
height: 480
visible: true
ApplicationWindow {
id: redWindow
x: mainWindow.x + mainWindow.width / 2
y: mainWindow.y + mainWindow.height / 2
width: 300
height: 400
flags: Qt.Popup | Qt.Dialog
visible: true
Rectangle {
color: "red"
anchors.fill: parent
}
}
}
There is a suggestion to make Popups proper windows here.

QML window is bouncing while changing size and position

My purpose is to glue the window to the right alignment of the screen while resizing.
During animation (or changing explicity) of window width and x (binded to width), ApplicationWindow is bouncing to left (flickering for changing explicity).
I've already was searching for the solution, but nothing is working for me.
Adding the attribute:
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
helped a lot, but window is still bouncing to left and right.
main.qml:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.15
ApplicationWindow {
id: root
height: 300
width: 300
visible: true
flags: Qt.FramelessWindowHint
x: Screen.width - width
Material.theme: Material.Dark
NumberAnimation on width {
id: animation
easing.type: Easing.InOutQuad
}
property var lowerSize: true
Rectangle {
anchors.fill: parent
Button {
anchors.centerIn: parent
enabled: !animation.running
text: lowerSize ? 'Size up' : 'Size down'
onClicked: {
animation.from = lowerSize ? 300 : 600
animation.to = lowerSize ? 600 : 300
animation.start()
lowerSize = !lowerSize
}
}
}
}
I've made example code for reproducing the issuee on github qml-flickering-example.
I had slightly different behavior on macOS than you are seeing in Windows (stutters on shrink for me) but it does indeed still stutter.
It appears to be because you are animating the width but then relying on QML bindings to update x. As a result, the x update is lagging behind the width update by one frame.
Using a ParallelAnimation and animating both at the same time fixed it for me:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.15
ApplicationWindow {
id: root
height: 300
width: 300
visible: true
flags: Qt.FramelessWindowHint
Component.onCompleted: {
x = Screen.width - width;
y = 0;
}
Material.theme: Material.Dark
ParallelAnimation {
id: animation
NumberAnimation {
id: widthAnimation
target: root
property: "width"
easing.type: Easing.InOutQuad
}
NumberAnimation {
id: xAnimation
target: root
property: "x"
easing.type: Easing.InOutQuad
}
}
property bool lowerSize: true
Rectangle {
anchors.fill: parent
Button {
anchors.centerIn: parent
enabled: !animation.running
text: lowerSize ? 'Size up' : 'Size down'
onClicked: {
widthAnimation.from = lowerSize ? 300 : 600
widthAnimation.to = lowerSize ? 600 : 300
xAnimation.from = lowerSize ? Screen.width - 300 : Screen.width - 600
xAnimation.to = lowerSize ? Screen.width - 600 : Screen.width - 300
animation.start()
lowerSize = !lowerSize
}
}
}
}

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 custom layout

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 :)

Qt5.5 image resizing jitter and not smooth

i'm learning Qt5. I start with a really simple QtQuick QML app with just one image filling the background. It works, but when i resize the window (Windows 8.1 64 bit), the resize is not smooth. There is substantial jitter and sometimes significant lag. It should be using OGL for this right?
Here's my code:
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
menuBar: MenuBar {
Menu {
title: qsTr("File")
MenuItem {
text: qsTr("&Open")
onTriggered: console.log("Open action triggered");
}
MenuItem {
text: qsTr("Exit")
onTriggered: Qt.quit();
}
}
}
MainForm {
anchors.fill: parent
}
}
and
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.2
Item {
visible: true
width: 640
height: 480
Image {
id: image1
sourceSize.height: 687
sourceSize.width: 1280
smooth: false
anchors.fill: parent
source: "images/showcase1280.jpg"
}
}
suggetions appreciated.
It is not smooth.
The image has a property named smooth the aim of which is to hold:
[...] whether the image is smoothly filtered when scaled or transformed.
Another interesting property is mimap, for which the documentation says that:
This property holds whether the image uses mipmap filtering when scaled or transformed.
Mipmap filtering gives better visual quality when scaling down compared to smooth, but it may come at a performance cost (both when initializing the image and during rendering).
Note that in your code you set:
smooth: false
Maybe you are doing it wrong if you want smooth changes, try setting the above mentioned properties to true.
I`m not pretend by solve your task. But i think you can use animation, as a variant:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1
Item {
Image {
anchors.centerIn: parent
width: parent.width
height: parent.height
sourceSize.height: 1000
sourceSize.width: 2000
source: "https://upload.wikimedia.org/wikipedia/ru/archive/8/88/20090512220306!Qt_logostrap_CMYK.png"
smooth: false
fillMode: Image.Stretch
asynchronous: true
Behavior on width {
animation: whAnimation
}
Behavior on height {
animation: whAnimation
}
NumberAnimation {
id: whAnimation
duration: 150
}
}
}

Resources