Reputation: 637
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.
Upvotes: 31
Views: 48004
Reputation: 11
You can create a custom Border in a separate qml file Stroke.qml
like below:
import QtQuick
import QtQuick.Controls.Material
Rectangle {
property int strokeLeft
property int strokeTop
property int strokeRight
property int strokeBottom
property var strokeColor: Material.accent
anchors.fill: parent
color: Material.primary
Rectangle {
visible: strokeLeft
width: strokeLeft
anchors {
left: parent.left
top: parent.top
bottom: parent.bottom
}
color: strokeColor
}
Rectangle {
visible: strokeTop
height: strokeTop
anchors {
left: parent.left
top: parent.top
right: parent.right
}
color: strokeColor
}
Rectangle {
visible: strokeRight
width: strokeRight
anchors {
top: parent.top
right: parent.right
bottom: parent.bottom
}
color: strokeColor
}
Rectangle {
visible: strokeBottom
height: strokeBottom
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
color: strokeColor
}
}
And then you can call it in your components like this:
// Border left
Stroke {
strokeLeft: 1
color: Material.accent
}
// Border top
Stroke {
strokeTop: 2
color: Material.accent
}
// Border right
Stroke {
strokeRight: 5
color: Material.accent
}
// Border bottom
Stroke {
strokeRight: 3
color: Material.accent
}
// Border top-left
Stroke {
strokeLeft: 1
strokeTop: 1
color: Material.accent
}
// Border for all sides
Stroke {
strokeLeft: 1
strokeTop: 1
strokeRight: 1
strokeBottom: 1
color: Material.accent
}
Upvotes: 0
Reputation: 131
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.
Upvotes: 4
Reputation: 17246
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.
Upvotes: 8
Reputation: 183
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
}
}
Upvotes: 5
Reputation: 4858
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.
Upvotes: 36