How does opacity work in QML? - qml

I don't understand the behavior of opacity in the following code!
import QtQuick 2.4
Rectangle {
id: root
width: 640; height: 480
Rectangle {
id: wrapper
width: 600; height:440
anchors.centerIn: parent
color: "black"
opacity: 0.5
Rectangle {
id: belowcover
width: cover.width / 2
height: cover.height / 2
anchors.centerIn: parent
color: "green"
z: 1
}
Rectangle {
id: cover
width: root.width / 2
height: root.height / 2
anchors.centerIn: parent
color: "red"
z: 1
}
Rectangle {
id: seen
width: 100; height: 100
radius: width
color: "blue"
z: -1
}
}
}
The wrapper has opacity of 0.5 so that I could see through it in order to see the circle seen. But both cover and belowcover have opacity of 1, and as belowcover is smaller than cover, it should not be seen (or rather I expect it not to be seen, or am I missing something?). But both cover and belowcover are seen. I want only the circle to be seen through wrapper, and belowcover is to remain hidden below cover. How can I do this? I have observed that setting the z of cover higher than that of belowcover does not make the latter hidden.
Edit:
I have observed that when opacity of parent is set to less than 1, the children objects become less opaque, even though their opacity remains at 1, as seen when printed to console. I don't understand why.

The reason why a child having opacity of 1 yet appearing to have transparency when its parent has opacity less than 1 is: opacity goes along the same line as other properties like x, y, etc. Thus, even though child has opacity of 1, it is relative to that of the parent. So if parent has opacity 0.5, and child has opacity of 1, then absolute opacity value of child is actually 0.5. Another child with opacity of 0.5 actually has opacity of 0.5x0.5=0.25. This is analogous to x value of child being 0, when absolute x may not be 0. This design preserves consistency throughout the API.
There are several work-arounds. The one I prefer most is to use semi-transparent colors for the parent. Try setting the color of wrapper to color: "#88000000". You can no longer see the green rectangle belowcover. To see that, you have to set the opacity of cover to some value less than 1, which means cover is opaque. That is how I actually solved my problem.
However, if the parent is an image, then this can't be applied. Then you have to resort to some other techniques. For example:
Using layer. Set layer.enabled: true for parent.
By changing the parent when immediate parent has opacity less than 1.
Many other techniques are listed here.

Related

Border-Shadow and decrease the size of parent element css in cytoscape

I have a following image:
I am trying to add border shadow to the rectangle shape. Is that possible in cytoscape? Also, the parent elements are Customers and order. Can I decrease the size of customers and order parent element?
Here's is the link to the code and the working example:
https://stackblitz.com/edit/angular-kpnys1?file=src%2Fapp%2Fdemo_test.json
Decreasing the parent size:
This is a styling issue, cytoscape.js applies padding to parent elements, if you want your parent element to be as small as possible, you'll have to adjust the padding in the :parent style:
{
selector: ":parent",
css: {
...
"padding": "0px" \\ remove padding completely, parent almost touching inner nodes
}
},
Border shadow
This was a little tricky, cytoscape.js only provides a normal border (like "border": "1px solid black"). You can use these styles:
border-width : The size of the node’s border.
border-style : The style of the node’s border; may be solid, dotted, dashed, or double.
border-color : The colour of the node’s border.
border-opacity : The opacity of the node’s border.
None of this provides us with the ability to apply a one sided border. As an alternative, I used the ghost styles:
ghost : Whether to use the ghost effect; may be yes or no.
ghost-offset-x : The horizontal offset used to position the ghost effect.
ghost-offset-y : The vertical offset used to position the ghost effect.
ghost-opacity : The opacity of the ghost effect.
If you adjust it a little bit, you can use the x offset and a nice opacity value to achieve this box shadow:
ghost: "yes",
"ghost-opacity": 0.5,
"ghost-offset-x": 1
Here is a working stackblitz with both changes applied.

QML - How to correctly set an implicitWith to a GridLayout

I'm using Qml 5.12 and basically trying to set an implicitWidth to a GridLayout.
For that, I have a purple rectangle and set the rectangle's width to the GridLayout.
The red rectangle fit with the GridLayout so I can see the width of my GridLayout.
Here's my code:
Rectangle { anchors.fill: gl; color: "red"; opacity: 0.22 }
Rectangle { id: rect; width: 350; height: 30; color: "purple"; }
GridLayout
{
id: gl
y: 35
implicitWidth: rect.width
columns: 2
Label { text: "This is a test" }
SpinBox { Layout.alignment: Qt.AlignRight }
}
If I run the code, I expect to have my both rectangle with the same width.
But the actual result is that the red rectangle is smaller. So the implicitWidth was not considerate.
Can anybody tell my why ?
Thank's !
The GridLayout compute its own implicitWidth based on its children's implicitWidth. So the value you set gets overwritten by the computed one.
implicitWidth is the width an Item wants to have (and the one it would have if no width is explicitely set). Setting it based on something else than its children or some internal value makes little sense.
Here you want the GridLayout to be the exact size of your Rectangle so just set its width property.

Make rectangle width fill ScrollView

I'm trying to get something in a ScrollView to expand in width to fit the screen. The ScrollView is anchored to the main window.
For example purposes, a Rectangle:
ScrollView {
anchors.fill: parent //mainWindow
Rectangle {
color: "light grey"
height: 1000
width: mainWindow.width
}
}
But when the vertical scrollbar appears, it obscures the Rectangle. I can sort of fix it by using a magic constant:
width: mainWindow.width - 20
But what if somebody has bigger scrollbars on their computer? Also it leaves an ugly empty space on the right when the vertical scrollbar is invisible.
Is there a way to automatically learn what the available space is inside of a ScrollView?
There is no need to explicitly adjust to scroll bar. You can just make it to fill the entire available parent space or so. And if you want specify margins:
ScrollView {
id: scrollView
anchors.fill: parent // mainWindow ?
anchors.centerIn: parent // anchoring as asked
anchors.margins: 20
contentItem:
Rectangle {
id: rectScroll
width: scrollView.viewport.width // set as viewport
height: 1000 // set to what you need
}
}
The original issue was solved mainly due to the width property of Rectangle set to parent.parent.width or scrollView.viewport.width as it is more adequate. The latter is definitely better, as long as the width of precisely viewport of scroll area and not the parent width (which in general not guaranteed to contain only this ScrollView).

Rectangle in QML that is transparent, except for the borders

Is there a way in QML to create a Rectangle with opacity: 0 that still have visible borders? If not, any suggestions on how to work around it?
Thanks
No, opacity is applied for complete visual aspect of item (and opacity:0 makes item full invisible). If you want rectangle with borders and without background, use "transparent" as color.
Rectangle { border.color: "black"; color: "transparent" }

QML - Control border width and color on any one side of Rectangle element

Currently i had a requirement of drawing a delegate rectangle with the help of ListView control. I was able to draw a series of rectangle either horizontal or vertical within the list view but the problem is with the border of the rectangle. The border width at the intersect point of the adjacent rectangle is of twice the width.
The delegate rectangle is nothing but a Qt Quick Rectangle element.
Is it possible to limit the border width on any one side of the rectangle alone?
Is it possible to change the color on any one side? (Something similar to QLineEdit - Where we can control the border width and color with respect to the sides)
Regards,
Santhosh.
You can make a custom border element like this :
CustomBorder.qml
import QtQuick 1.0
Rectangle
{
property bool commonBorder : true
property int lBorderwidth : 1
property int rBorderwidth : 1
property int tBorderwidth : 1
property int bBorderwidth : 1
property int commonBorderWidth : 1
z : -1
property string borderColor : "white"
color: borderColor
anchors
{
left: parent.left
right: parent.right
top: parent.top
bottom: parent.bottom
topMargin : commonBorder ? -commonBorderWidth : -tBorderwidth
bottomMargin : commonBorder ? -commonBorderWidth : -bBorderwidth
leftMargin : commonBorder ? -commonBorderWidth : -lBorderwidth
rightMargin : commonBorder ? -commonBorderWidth : -rBorderwidth
}
}
main.qml
import QtQuick 1.0
Rectangle
{
width: 500
height: 500
color: "grey"
Rectangle
{
anchors.centerIn: parent
width : 300
height: 300
color: "pink"
CustomBorder
{
commonBorderWidth: 3
borderColor: "red"
}
}
Rectangle
{
anchors.centerIn: parent
width : 200
height: 200
color: "green"
CustomBorder
{
commonBorder: false
lBorderwidth: 10
rBorderwidth: 0
tBorderwidth: 0
bBorderwidth: 0
borderColor: "red"
}
}
Rectangle
{
anchors.centerIn: parent
width : 100
height: 100
color: "yellow"
CustomBorder
{
commonBorder: false
lBorderwidth: 0
rBorderwidth: 0
tBorderwidth: 10
bBorderwidth: 10
borderColor: "blue"
}
}
}
In this example I have used the custom element to make different rectangles which have border on all, one or two sides.
The simplest solution for a ListView is to give your delegate a 1 pixel border and then use a spacing of -1 to get each cell to overlap the other by 1 pixel:
ListView {
spacing: -1
delegate: Rectangle {
height: 40
width: parent.width
border.width: 1
border.color: "black"
z: listView.currentIndex === model.index ? 2 : 1
...
}
...
}
It should work the same for other border widths.
EDIT: Added a nice enhancement from comment below that makes sure the selected item's border is always above all others so that if you change it to indicate selection it's not obscured by its neighbor delegates.
If you're trying to add borders between items in ListView, you should use the given property 'spacing' to establish a common border between each item. Then you could potentially add a background to the ListView to customize border colors.
Example:
ListView {
spacing: 1 // or whatever you want the border to be
}
...But if you really want a specific border you could always use Rectangles to make your own borders:
Item { // this is your 'rectangle'
Rectangle { // the main thing
id: rec
anchors.fill: parent
anchors.leftMargin: 2
anchors.rightMargin: 5
// etc
}
Rectangle { // a border example
anchors.right: rec.right
height: parent.height
width: 5
color: "red"
// etc
}
}
A bit late to answer but the accepted solution draws the border outside the geometry of the rectangle which can be problematic in some cases.
Another way to do this is to do something like:
// CustomBorderRect.qml
import QtQuick 2.12
Item
{
property alias color: innerRect.color
property alias borderColor : borderRect.color
property int borderWidth: 0
property int lBorderwidth : borderWidth
property int rBorderwidth : borderWidth
property int tBorderwidth : borderWidth
property int bBorderwidth : borderWidth
Rectangle
{
id: borderRect
anchors.fill: parent
Rectangle
{
id: innerRect
anchors {
fill: parent
leftMargin: lBorderwidth
rightMargin: rBorderwidth
topMargin: tBorderwidth
bottomMargin: bBorderwidth
}
}
}
}
This can then be used like this:
CustomBorderRect
{
width : 50
height: 30
color: "lightseagreen"
lBorderwidth: 0
rBorderwidth: 5
tBorderwidth: 5
bBorderwidth: 0
borderColor: "lightyellow"
}
This way the border is drawn with the given geometry.