QML - DropShadow blurring text & img - qt

I'm trying to apply a DropShadow effect into my Rectangle. After I did it, text and icon inside are getting blurred. Any idea how to fix it?
import VPlayApps 1.0
import QtQuick 2.9
import QtGraphicalEffects 1.0
import QtQuick.Controls 2.2
App {
Rectangle {
id: buttonOverview
width: app.width * 0.12
height: buttonQuit.width
color: "#439fd0"
radius: 3
anchors.left: parent.left
anchors.leftMargin: app.width * 0.034
gradient: Gradient {
GradientStop {
position: 0
color: "#48a4d5"
}
GradientStop {
position: 1
color: "#01618c"
}
}
AppImage {
id: appImage
width: 44
height: 43
anchors.bottom: spacerProjectOverview.top
anchors.horizontalCenter: parent.horizontalCenter
source: "../../../WinCan/Icons/projectOverview.png"
fillMode: Image.PreserveAspectFit
}
Text {
id: textOverview
color: "#ffffff"
text: qsTr("Project\nOverview")
anchors.topMargin: 5
anchors.top: spacerProjectOverview.bottom
anchors.bottomMargin: parent.height * 0.18
anchors.bottom: parent.bottom
font.bold: true
horizontalAlignment: Text.AlignHCenter
anchors.horizontalCenter: parent.horizontalCenter
font.pixelSize: 14
}
MouseArea {
anchors.fill: parent
onClicked: {
buttonQuit.opacity = 0
}
}
Rectangle {
id: spacerProjectOverview
width: parent.width
height: parent.height * 0.05
color: "transparent"
anchors.verticalCenter: parent.verticalCenter
}
anchors.verticalCenter: parent.verticalCenter
}
DropShadow {
anchors.fill: buttonOverview
horizontalOffset: 1
verticalOffset: 6
radius: 5
samples: 5
source: buttonOverview
color: "black"
}
}
Expected : Getting shadow and nice looking text and icons
Actual : Getting shadow but text and icons are blurry

Your DropShadow is being applied to buttonOverview components area and as it is defined below the buttonOverview it will be positioned on top of it. If i am understanding your requirements you should move the DropShadow above the buttonOverview Rectangle component.

Related

QML - SpinBox - Data validation

I have the following SpinBox model which I am trying to recreate using the new QtQuick.Control 2, because this one it's using version 1. And I've encountered some problems which I am not sure how to solve.
On the validation side, I should not be able to write anything on the suffix side, just on the number part. Also I should not be allowed to remote the suffix from there while editing
My width should be fixed and I should not be allowed to write more than that.
My Code:
import QtQuick 2.6
import QtQuick.Controls 2
import QtQuick.Controls.Styles 1.4
import QtGraphicalEffects 1.0
SpinBox {
id: root
property color borderColor: "red"
property string multipleValuesTooltip: ""
property color backgroundColor: "yellow"
property bool showTooltip: true
font.pointSize: 10
property int maximumValue: 50
property int minimumValue: 0
property string suffix: ""
property int decimals: 0
to: maximumValue
from: minimumValue
editable: true
rightPadding: {
console.log(root.contentItem.height)
return Math.max(40, Math.round(root.contentItem.height))
}
textFromValue: function(value, locale) {
return qsTr("%1"+suffix).arg(value);
}
contentItem: TextInput {
z: 5
text: root.textFromValue(root.value, root.locale)
font: root.font
color: "white"
selectionColor: "#21be2b"
selectedTextColor: "#ffffff"
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
validator: root.validator
inputMethodHints: Qt.ImhFormattedNumbersOnly
}
up.indicator: Rectangle {
height: parent.height / 2
anchors.right: parent.right
anchors.top: parent.top
implicitWidth: 20 // Adjust width here
implicitHeight: {
console.log(root.contentItem.height)
return root.contentItem.height - 10
}
color: root.up.pressed ? "red" : "pink"
Image {
source: "qrc:/resources/arrow-down.png"
height: Math.min(15, sourceSize.height)
width: Math.min(30, sourceSize.width)
anchors.centerIn: parent
rotation: 180
}
}
down.indicator: Rectangle {
height: parent.height / 2
anchors.right: parent.right
anchors.bottom: parent.bottom
implicitHeight: root.contentItem.height - 10
implicitWidth: {
console.log("W: ",root.width)
return 20
}
color: root.down.pressed ? "red" : "pink"
Image {
source: "qrc:/resources/arrow-down.png"
height: Math.min(15, sourceSize.height)
width: Math.min(30, sourceSize.width)
anchors.centerIn: parent
}
}
background: Item {
implicitHeight: root.height === 0 ? Math.max(30, Math.round(root.contentItem.height * 1.2)) : root.height
implicitWidth: root.contentItem.width + leftPadding +rightPadding
baselineOffset: root.anchors.baselineOffset
Rectangle {
id: baserect
anchors.fill: parent
color: "purple"
radius: 3
}
Rectangle { // Border only
anchors.fill: parent
border.color: "black"
color: "transparent"
radius: 3
}
Rectangle {
anchors.right: parent.right
anchors.rightMargin: root.rightPadding - 10
anchors.verticalCenter: parent.verticalCenter
color: "black"
height: parent.height - parent.height/5
width: 1
}
}
}
I couldn't find any documentation or any kind of information regarding this wherever I've searched for. If any of you could help me I would be really grateful.

Implementing a slider in QML with a VU-meter like image as a background

I am trying to create a slider that I can move up and down with my mouse. However, I want to use my own image as the background. I am currently trying to implement this with a OpacityMask. Basically, I am trying to make the opacity 0 from where the handle is to the right end of the slider.
I would ordinarily just move a rectangle that is same color as the background over it. However, I want whatever element is under the slider to be displayed when the slider is pulled back.
How can I create this behavior?
import QtQuick 2.7
import QtQuick.Templates 2.0 as T
import QtGraphicalEffects 1.12
import "."
T.Slider {
id: control
implicitWidth: 200
implicitHeight: 26
handle: Rectangle {
x: control.visualPosition * (control.width - width)
y: (control.height - height) / 2
width: 20
height: 15
radius: 5
color: control.pressed ? "#f0f0f0" : "#f6f6f6"
border.color: "gray"
}
background: OpacityMask {
anchors.fill: sliderImage
source: sliderImage
maskSource: mask
}
Image{
id: sliderImage
source: "./Jarvis2/images/volume_barH.png"
height: 20
width: parent.width
visible: false
}
Item{
id: mask
anchors.fill: sliderImage
Rectangle{
id: outer
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
width: control.visualPosition*parent.width
color: "gray"
opacity: 1
visible: false
}
Rectangle {
id: inner
color: "transparent"
z: 1
opacity: 1
anchors.left: outer.right
anchors.right: parent.right
anchors.top: outer.top
anchors.bottom: outer.bottom
visible: false
}
}
}
The slider at 100%:
The slider at around 70%:
The slider at around 24%
I think you can omit the OpacityMask and simply use a clipping Item:
Slider {
id: slider
width: 100
height: 300
orientation: Qt.Vertical
background: Item {
id: background
Item {
clip: true
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: (1 - slider.visualPosition) * slider.height
Rectangle { //Your image goes here
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: background.height
gradient: Gradient {
GradientStop { position: 0; color: "blue" }
GradientStop { position: 1; color: "red" }
}
}
}
}
}
You might have to fiddle a bit with the height of the clipping Item since there is some padding involved.
If you nevertheless want to use OpacityMask (because you want a different shape), you should put them together in the background:
Slider {
id: slider
width: 100
height: 300
orientation: Qt.Vertical
background: Item {
id: background
Rectangle { //Your image goes here
id: image
anchors.fill: parent
visible: false
gradient: Gradient {
GradientStop { position: 0; color: "blue" }
GradientStop { position: 1; color: "red" }
}
}
OpacityMask {
anchors.fill: parent
source: image
maskSource: mask
}
Item {
id: mask
visible: false
anchors.fill: parent
Rectangle {
radius: 10
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: parent.height * slider.position
color: "white"
}
}
}
}

How to set visible flag correctly for Text item in QML based on a model count of ListView?

I have the following QML code where I show list view based on a model fetched from a C++ AbstractListModel.
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.12
import QtQuick.Controls.Styles 1.4
import HackNews 1.0
import QtWebEngine 1.8
Item {
width: 640
height: 480
property alias dummyModel: kidsListView.model
ListView {
width: 100;
id: listView
anchors.left: parent.left
anchors.leftMargin: 20
anchors.top: parent.top
anchors.topMargin: 20
anchors.bottom: parent.bottom
anchors.bottomMargin: 20
model: HackNewsModel
delegate: Rectangle
{
width: 100; height: 40
Button {
id: pushButton
anchors.fill: parent
anchors.margins:
{
right: 5
left: 5
top: 5
bottom: 5
}
text: "id "+model.id
style: ButtonStyle{
background: Rectangle {
implicitWidth: 100
implicitHeight: 25
border.width: control.activeFocus ? 2 : 1
border.color: "#888"
radius: 4
gradient: Gradient {
GradientStop { position: 0 ; color: control.pressed ? "#ccc" : "#eee" }
GradientStop { position: 1 ; color: control.pressed ? "#aaa" : "#ccc" }
}
}
}
onClicked:
{
dummyModel = HackNewsModel.get(model.listId).kids
}
}
}
}
Rectangle
{
id: rectangle
anchors.left: listView.right
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: parent.top
anchors.margins:
{
left: 20
right: 20
top: 20
bottom: 20
}
Text {
id: kidsHeader
anchors.top: parent.top
anchors.left: parent.left
width: 100
height: 20
visible: (dummyModel.count!==0)?true:false
text: "kids"
}
ListView {
anchors.top: kidsHeader.bottom
anchors.left: parent.left
id: kidsListView
anchors.leftMargin: 10
model: ListModel{}
height: 50
delegate: Text {
text: modelData
}
ScrollBar.vertical: ScrollBar {}
}
}
}
The model can empty sometimes. When it's not empty, I would like to show a Text item otherwise I want to hide it. But somehow it's set visible forever when I have visible: (dummyModel.count!==0)?true:false or never when I have visible: (dummyModel.count>0)?true:false.
When model isn't empty it looks as the following.
But when the model isn't empty the text item doesn't get hidden.
Could you please tell me what am I doing wrong?
Thanks.
There is a property count available on the ListView as well, you should use that:
Text {
id: kidsHeader
anchors.top: parent.top
anchors.left: parent.left
width: 100
height: 20
visible: kids_listview.count !== 0 //Important change here
text: "kids"
}
ListView {
id: kids_listview
anchors.top: kidsHeader.bottom
anchors.left: parent.left
id: kidsListView
anchors.leftMargin: 10
model: ListModel{}
height: 50
delegate: Text {
text: modelData
}
ScrollBar.vertical: ScrollBar {}
}

Apply QML DropShadow invalid, error hint and hint for "QML DropShadow: Cannot anchor to an item that isn't a parent or sibling."

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
}
}

Qml Text Size based on Container

I am using Qt Quick to develop an app (Qt 5.8). I have text that appears in multiple places so I created a component to use to display the text. The areas the text can vary in placement and size. How can I adjust my text so that the data displays in 1 line horizontally and all text is the same size if I simply want to display the following?
FLAPS 1
GEAR DOWN
TRIM -1.0
I used Text and was able to get close, however since GEAR DOWN has more characters the text was smaller, than flaps and trim. So I moved on to using Label. Can someone provide better insight on how to have text size based on its container's width or height?
main.qml
import QtQuick 2.6
import QtQuick.Window 2.2
Window {
id: windowRoot
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle{
height: windowRoot.height * .80
width: windowRoot.width * .80
color: "green"
anchors.centerIn: parent
Rectangle {
id: rect1
opacity: .5
anchors.top: parent.top
anchors.left: parent.left
color: "lime"
border.color: "orange"
height: parent.height * 1/2
width: parent.width * 1/2
TextHolder {
anchors.top: parent.top
anchors.left: parent.left
width: parent.width * 1/4
height: parent.height
}
}
Rectangle {
id: rect2
anchors.top: parent.top
anchors.left: rect1.right
color: "yellow"
border.color: "blue"
height: parent.height * 1/2
width: parent.width * 1/2
}
Rectangle {
id: rect3
anchors.top: rect1.bottom
anchors.left: parent.left
color: "pink"
border.color: "red"
height: parent.height * 1/2
width: parent.width * 1/2
TextHolder {
anchors.top: parent.top
anchors.left: parent.left
width: parent.width * 1/4
height: parent.height * 1/2
}
}
Rectangle {
id: rect4
anchors.top: rect2.bottom
anchors.left: rect3.right
color: "orange"
border.color: "lime"
height: parent.height * 1/2
width: parent.width * 1/2
TextHolder {
anchors.bottom: parent.bottom
height: parent.height * 1/4
width: parent.width * 1/4
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
TextHolder.qml
import QtQuick 2.0
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.1
Rectangle {
color: "purple"
border.color: "steelblue"
border.width: 3
property color colorOfText: "white"
property real textSize: 48
Item {
id: inputs
property int flapHndl: 1
property int gearHndl: 1
property real trim: -1.0
}
clip: true
ColumnLayout {
anchors.top: parent.top
width: parent.width
height: parent.height
spacing: 5
Label {
id: flapLabel
text: "FLAPS " + inputs.flapHndl
color: colorOfText
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: textSize
fontSizeMode: Text.HorizontalFit
Layout.fillWidth: true
}
Label {
id: gearLabel
text: {
if (inputs.gearHndl === 1)
return "GEAR DOWN"
else
return "GEAR UP"
}
color: colorOfText
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: textSize
fontSizeMode: Text.HorizontalFit
Layout.fillWidth: true
}
Label {
id: trimLabel
text: "TRIM " + inputs.trim.toFixed(1)
color: colorOfText
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: textSize
fontSizeMode: Text.HorizontalFit
Layout.fillWidth: true
}
}
}
Can someone provide better insight on how to have text size based on
its container's width or height?
For evaluating the text width and height we can definitely use QML type TextMetrics and having the metrics we can then attempt to fit the text in. If the text still won't fit we can then try to adjust the font size. For that, some logic might need to be implemented with JavaScript. So, the below code is an example of the "feedback" type of solution.
Rectangle {
property string textToShow
property int widthLimit: 400
onTextToShowChanged: {
while (txtMeter.width > widthLimit) {
txtMeter.font.pixelSize --;
}
}
TextMetrics {
id: txtMeter
font.family: "Courier"
font.pixelSize: 25
text: textToShow
}
Text {
font: txtMeter.font
text: textToShow
}
}
P.S. This is just a sketchy idea and your actual implementation may differ
There is fontSizeMode property of Text
Text {
id: goToParentFolderText
anchors.fill: parent
font.family: fontAwesomeSolid.name
text: "\uf060"
fontSizeMode: Text.Fit
font.pointSize: 100
color: Material.accent
}
I was able to get #Alexander V's answer to work, with a minor change. The outer textToShow property was processing its update before the TextMetrics block was updated (which caused the width calculation to be incorrect). You can fix this issue by triggering onTextChanged inside the TextMetrics blocks instead.
Rectangle {
property string textToShow
property int widthLimit: 400
TextMetrics {
id: txtMeter
font.family: "Courier"
font.pixelSize: 25
text: textToShow
onTextChanged: {
while (txtMeter.width > widthLimit) {
txtMeter.font.pixelSize --;
}
}
}
Text {
font: txtMeter.font
text: textToShow
}
}

Resources