How to set TextField's underline color? - qt

How do you set the color of the line in TextField to another color?
With Material theme you can change "Material.accent" color, but I want to change the permanent color, not only when the line gets focus.

There are at least 2 types of TextField - QtQuick2 and QtControls2. Assuming that you use the last one you can customize the control as you want, including the line color. For example:
TextField {
anchors.centerIn: parent
background: Item {
implicitWidth: 200
implicitHeight: 40
Rectangle {
color: "yellow"
height: 3
width: parent.width
anchors.bottom: parent.bottom
}
}
}

if you check source code of the Material style you see next:
background: Rectangle {
y: source.height - height - source.bottomPadding + 8
implicitWidth: 120
height: source.activeFocus || source.hovered ? 2 : 1
color: source.activeFocus ? source.Material.accentColor
: (source.hovered ? source.Material.primaryTextColor : source.Material.hintTextColor)
}
So for add support custom color of TextField line you need to add one property and replace source.Material.hintTextColor to your custom color.
TextField {
id: source
property color lineColor: "#ff00ff"
background: Rectangle {
y: source.height - height - source.bottomPadding + 8
implicitWidth: 120
height: source.activeFocus || source.hovered ? 2 : 1
color: source.activeFocus ? source.Material.accentColor
: (source.hovered ? source.Material.primaryTextColor : source.lineColor)
}
}

Related

Putting an element between a child and parent (z values) QML

I was working with a GridView in QML. When I click on an element, I want to following highlight to happen:
However, my problem is that I want the blue color to appear below the delegate (not in the white area but still visible on the transparent side part) while the checkmark appears above (so it is visible). I have tried playing around with the z values so that the lowest z should be the blue rectangle, the middle should be the white rectangle part of the delegate, and the highest should be the check mark but i can't seem to make it work. Either the highlight or the delegate has to be on top. Does anyone know any way I can fix this so that it works correctly?
Code for highlight:
highlight:
Rectangle {
z:5
color: "steelblue"; radius: 5; opacity: 0.5
Image{
z:8
id: checkMark
visible: found;
x: parent.width-8-width
y: 8
width: 40;
height: 40;
source: "file:///Users/arjun/Documents/CompetitiveBall/images/checkMark.png"
}
}
Code for delegate:
Component {
id: contactsDelegate
Rectangle{
width: grid.cellWidth
height: grid.cellHeight
color: "transparent"
Rectangle {
z:7
width: grid.cellWidth-20
height: grid.cellHeight-20
id: wrapper
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
border.width: 3
border.color: "black"
radius: 5;
Image{
id: mImage
x:parent.x
width: 65
height:65;
source: picSource
}
Text{
width: grid.cellWidth-15
y: mImage.y+mImage.height+4
anchors.horizontalCenter: parent.horizontalCenter
id: nameText
text: name
font.family: "Palatino Linotype"
font.bold: (grid.isCurrentItem===true)?"true":"false"
horizontalAlignment: Text.AlignHCenter
color:"#050027"
}
MouseArea{
anchors.fill: parent
onClicked:{
console.log("Clicked on :" + name)
//what happens when u click
grid.currentIndex=index;
}
}
}
}
}
Since you want part of the highlight to be underneath the delegate and part of it to be on top, you need to break it up into different pieces. I tested the code below with Qt 5.15.0. I made the normal highlight object draw underneath the delegate. Then I added another Rectangle that follows the highlight that draws on top of the delegate.
GridView
{
id: lv
anchors.fill: parent
anchors.margins: 50
cellWidth: 50
cellHeight: 50
model: 30
// By default, highlight draws behind delegates
// (You can specify a positive z-value to make it draw on top)
highlight: Item
{
Rectangle
{
anchors.centerIn: parent
width: 50
height: 50
color: "green"
}
}
delegate: Rectangle
{
width: 30
height: 30
color: "red"
MouseArea
{
anchors.fill: parent
onClicked: lv.currentIndex = index;
}
}
// This will draw on top of the delegates
// (You can change that by specifying a negative z-value.)
Rectangle
{
id: checkbox
x: lv.highlightItem.x - lv.contentX
y: lv.highlightItem.y - lv.contentY
width: 10
height: 10
color: "blue"
}
}

Transparent button text over the background

I am trying to make transparent text in qml.
I have a customized button:
ApplicationWindow {
visible: true
width: 320
height:240
style: ApplicationWindowStyle {
background: Image { // paste any url here
source: "https://t4.ftcdn.net/jpg/01/05/18/57/240_F_105185755_w384KDBvemK5Mn4oXzrWbCz9SRvHuDIh.jpg"
}
}
Button
{
anchors.centerIn: parent
style: ButtonStyle
{
padding
{
left: 16
right: 16
top: 8
bottom: 8
}
background:
Rectangle
{
antialiasing: true
color: control.pressed ? "#d1d1d1" : control.hovered ? "#666" : "transparent"
border.color: "white"
radius: height/2
border.width: 1
}
label:
Text
{
text: "buttonText"
color: control.pressed ? "white" : control.hovered ? "#00000000" : "white"
}
}
}
}
All I want is to have transparent text in button in hovered state. Text should have the color of background. Example:
upd. I need this to work without shaders on slow pc.
One option would be to use a custom QQuickPaintedItem and use a QPainterPath to draw the "text shaped hole".
Basically like this
void MyItem::paint(QPainter *painter)
{
QPainterPath path;
path.addRect(0, 0, width(), height());
path.addText(textX, textY, font, yourText);
painter->setBrush(yourBackgroundColor);
painter->setPen(Qt::transparent);
painter->drawPath(path);
}
The position, i.e. textX and textY, would have to be calculated manually I am afraid, though QFontMetrics::boundingRect() should help there.

QT Quick - TextField background and borde

I am starting with QT and trying to style a TextField using the following QML code:
property Component textfieldStyle: TextFieldStyle {
background: BorderImage {
source: control.focus ? "images/input-border-focused.png" : "images/input-border.png"
border.left: 0 ; border.right: 0 ; border.top: 0 ; border.bottom: 4
}
}
My question is: is there a way of setting a border like this and also an icon inside the field just like in the image below?
The blue part is the background of the window.
If so, how can it be done?
Thank you in advance.
Well since you have to use a Component for the TextFieldStyle, you are not restricted to use BorderImage, you can create your own Field using for eg a Rectangle like this
TextField {
style: TextFieldStyle {
textColor: "black"
background: Rectangle {
radius: 2
border.color: "red"
border.width: 3
Image {
width: 10
height: 10
source: "qrc:///inner.png"
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 10
}
}
}
}
Since Rectangle has border property you can use it directly to set border.

How to access the buttonStyle object inside of one button using JavaScript in QML 5.2

Below is my Qml code:
Button {
id: newMenu
anchors {
top: topMenu.top
topMargin: 15
left: topMenu.left
leftMargin: 16
}
text: "New"
iconSource: "../images/New.png"
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true //this line will enable mouseArea.containsMouse
onClicked: {
newProjectFileDlg.visible = true
}
onEntered: {
console.log(tt1);
}
}
style: ButtonStyle {
id: buttonStyle
background: Rectangle {
id: tt1
implicitWidth: 100
implicitHeight: 25
border.width: 0
radius: 4
color: mousearea.entered ? "lightsteelblue" : "#2e2e2e"
}
}
I want to access this button's style property, change the background.color when mouse is hover. But the console.log outpu is always
qrc:/qmls/menu.qml:40: ReferenceError: tt1 is not defined
How to get the element using JavaScript? Or do we have other approach to change background color when mouse is entered.
Answering to your question, you should define public property like:
Button {
id: root
property color backgroundColor: pressed ? 'skyblue'
: mousearea.entered ? "lightsteelblue"
: "#2e2e2e"
...
MouseArea { id: mousearea; ... }
style: ButtonStyle {
background: Rectanlge { color: root.backgroundColor; ... }
}
}
and then use is property to override default implementation.
But,
You are trying to use styles in a completely wrong way. Style is a visual representation of Control's state and should't be changed manually in run-time. So, a proper way is to bind control properties to style (e.g. using property control).
style: ButtonStyle {
background: Rectangle {
color: control.hovered ? 'lightsteelblue'
: 'skyblue'
}
}
You can achieve something similar without using styles by nesting a rectangle inside the button and then using the onHoveredChanged property to modify the opacity. An example is below. I did it this way to avoid conflicting with the normal button style's hover effect.
Button {
text: "Push me"
Rectangle{
id: myRectId
anchors.fill: parent
anchors.margins: 1
color: "green"
opacity : .2
}
onHoveredChanged: hovered ? myRectId.opacity = 0 : myRectId.opacity = .2;
}
This ends up looking like this:

Stretching element to contain all children

How is it possible in QML to automatically stretch element so that all its childs fit in it? And how to specify spacing? For example, I would like to have a rectangle around a text. The rectangle should have some internal spacing.
If I write the following then the rectangle has a size of 0,0.
Rectangle {
color: "gray"
anchors.centerIn: parent;
Text {
text: "Hello"
}
}
If I try to fix it by using the Column element, as suggested in How to make QML items to grow to fit contents?, then I get a column through the whole window/parent,
Column {
anchors.centerIn: parent
Rectangle {
color: "gray"
anchors.fill: parent
}
Text {
anchors.centerIn: parent
text: "Hello"
}
}
Edit:
I have also tried to use the Flow element instead of Column, but then I got a row through the whole window/parent.
You can use the childrenRect property for this:
import QtQuick 2.0
Rectangle {
width: 320
height: 200
Rectangle {
color: "BurlyWood"
anchors.centerIn: parent
width: childrenRect.width + 20
height: childrenRect.height + 20
Text {
id: hello
x: 10
y: 10
text: "Hello"
}
Text {
anchors.left: hello.right
anchors.leftMargin: 10
anchors.top: hello.top
text: "World"
}
}
}
However, note that using childrenRect in combination with using anchors.centerIn: parent in one of the direct children yields a warning about a binding loop.
Setting the width and height manually works, but is a little ugly:
Rectangle {
color: "gray"
width: label.width+20
height: label.height+20
anchors.centerIn: parent
Text {
id: label
anchors.centerIn: parent
text: "Hello"
}
}
I don't think using chilrenRect property is sufficient (as suggested by Thorbjørn Lindeijer). It doesn't automatically take into account all various margins of the child(ren) element(s). If the latter changes, the root rectangle doesn't automatically adjust its size. I personally came with the following solution:
Rectangle {
color: "white"
implicitWidth: row.implicitWidth + extraLeft + extraRight
implicitHeight: row.implicitHeight + extraTop + extraBottom
property int extraMargin: row.anchors.margins ? row.anchors.margins : 0
property int extraTop: row.anchors.topMargin ? row.anchors.topMargin : extraMargin
property int extraBottom: row.anchors.bottomMargin ? row.anchors.bottomMargin : extraMargin
property int extraLeft: row.anchors.leftMargin ? row.anchors.leftMargin : extraMargin
property int extraRight: row.anchors.rightMargin ? row.anchors.rightMargin : extraMargin
RowLayout {
id: row
spacing: 50
anchors.fill:parent
anchors.margins: 50
anchors.leftMargin: 100
Label {
text: "hello"
}
Label {
text: "world"
}
}
}

Resources