How to define gradient color globally? - qt

I have Gradient in my QML as shown below example. Is it possible to define color "#1AD6FD" or "#1D62F0" globally in QML?
gradient: Gradient {
GradientStop { position: 0.00; color: "#1AD6FD" }
GradientStop { position: 1.00; color: "#1D62F0" }
}

You can define custom properties on any QML object like this.
Rectangle {
id: root
// you can define your on custom properties like this
property color gradientColor1: "#1AD6FD"
property color gradientColor2: "#1D62F0"
}
And then use it in any other item that has access to the object where it is defined via the id.
Item {
gradient: Gradient {
GradientStop { position: 0.00; color: root.gradientColor1 }
GradientStop { position: 1.00; color: root.gradientColor1 }
}
}
You could also define the whole gradient globally if you like to reuse that.
If you want access to the properties from other QML files there are multiple ways to do that. If you have access to the QML root object you can also access its properties from other files or you can define a global JavaScript library with some constants for color values, but not whole QML objects in there I think (only pure JS).
Another simple way is to define an independent QML object with just some global properties for your project and include that in your other QML files with just an id to reference it, that is maybe the easiest solution.
Just define an empty QML-Item with some properties like the Rectangle example above and include it in your other QML files like this
Rectangle {
id: root
// include your custom QML global item (GlobalProperties.qml)
GlobalProperties {
id: globalProperties
}
// then you can use it like before, i.e.
color: globalProperties.gradientColor1 // color prop from your GlobalProperties.qml
}

Related

Proper way to set a child item property in QML

Everyone knows about how to set a background for Buttons, Popups etc via the background property of these elements. But I am wondering, how can I create such a property myself for my own custom elements? I found a way but it looks pretty ugly and I can't seem to find the qml code for Button, Popup etc where said property is defined. So i played a bit and came up with the idea of using Bindings like this:
Item {
id: root
property Item background: Rectangle {
color: "red"
}
Binding {
target: root.background
property: "parent"
value: root
}
Binding {
target: root.background
property: "anchors.fill"
value: root
when: root.background.parent == root
delayed: true
}
}
As mentioned that looks pretty tiresome if you need to declare a lot of properties of the child. So, how does Qt do it or what is the proper way of doing it?
// ItemWithBackground.qml
Item {
property alias background: backgroundLoader.sourceComponent
Loader {
id: backgroundLoader
anchors { fill: parent }
sourceComponent: Rectangle { color: 'red' } // default background implementation
}
}
// Usage example:
ItemWithBackground {
background: Rectangle {
color: 'green'
}
}
If you’re on a recent Qt version, have a look at using inline components. They allow you to create API’s like this easily.

Qt: Style depending on label value

I have what looks like a very simple problem: I want to design a QLabel whose value changes dynamically (no issue here) and whose background color changes accordingly (this is the issue).
Of course, I know I can do something like that (pseudo code):
function on_new_value(value):
label.setText(value)
if value>10:
label.setBackgroundColor(RED)
else if value<0:
label.setBackgroundColor(RED)
else:
label.setBackgroundColor(GREEN)
But that kind of mixes model and view. What I'd like, ideally, would be to be able to use an extended version of Qt Stylesheets as follows:
QLabel { background: green; }
QLabel { if value>10: background: red; }
QLabel { if value<0: background: red; }
Obviously, that is not possible. But I'm wondering if Qt allows for something close in order to embbed (for instance in a class) a graphic behaviour based on a value.
I know about QPalette, but the style condition is only about the widget Active/Disable state, not its "value".
In other words, I'm looking for sort of a ValueDependantStyle class or somehting close.
Any pointers? Am I looking at this all wrong?
Edit: in case this is important, I'm developping with PyQt5.
You could use a "model property" on the label, that defines the color in a style sheet (cf. Qt Style Sheet Reference about properties):
function on_new_value(value):
label.setText(value)
if value>10:
label.setProperty("HasError", "true")
else if value<0:
label.setProperty("HasError", "true")
else:
label.setProperty("HasError", "false")
QLabel[HasError="false"] { background: green; }
QLabel[HasError="true"] { background: red; }

In QML, how can I create a parent Component that takes child Component instances and puts them in the parent Components hierarchy?

Qt's QML has a number of widgets where you instantiate the widget and then give it an instance of a Component for it to display and use.
For example, the Popup widget can be used like:
Popup { // <-- Parent Component
Rectangle { // <-- Child Component
width: 100;
height: 100;
color: 'red';
}
}
How can I do this myself? How can I write a custom QML Component that will take a child Component instance and put it beneath my tree?
If I have a silly Component like:
// File Parent.qml
Rectangle {
default property var child_inst;
width: child_inst.width + 20;
width: child_inst.width + 20;
color:'red';
child_inst; // <-- how is this done?
}
and used like:
Parent {
Text { text: 'hello world!' }
}
What is the syntax or mechanism by which I can instantiate or move the child_inst to be a child of my Parent?
Wow, that's hella confusing way to put it, but if I understand correctly, you want to have children actually redirected to some other object automatically. This is possible, for example:
// Obj.qml
Rectangle {
width: 50
height: 50
default property alias content: row.children
Row {
id: row
}
}
and then:
Obj {
Rectangle {
width: 10
height: 10
color: "red"
}
Rectangle {
width: 10
height: 10
color: "green"
}
Rectangle {
width: 10
height: 10
color: "blue"
}
}
The result is that the rgb rectangles are displayed in a row, because even though they are nested in Obj, they are internally delegated to the row.
Using a default property means that you don't have to specify it manually. Of course, if you don't want that, you can even use multiple different placeholders, for example, you can have:
property alias content: contentItem.children // this is a column of contents
property alias control: buttons.children // this is a row of buttons
Keep in mind that if you don't use the default property, you will have to specify the objects as a comma separated list in the case they are multiple:
Obj {
content : [
Rectangle {
width: 10
height: 10
color: "red"
},
Rectangle {
width: 10
height: 10
color: "green"
},
Rectangle {
width: 10
height: 10
color: "blue"
}
]
}
This is not necessary if it is a single object, it can be created like this:
Obj {
content : Rectangle {
width: 10
height: 10
color: "green"
}
}
But you can also use a single target and have your row nest the objects externally, which can save you having to bother with the array notation and gives you more flexibility:
Obj {
content : Row {
// bunch of stuff here
}
}
In this case, the content can be a simple positioned Item, that will serve as a placeholder, as it is the case for the popup component.
And finally, you can also use a Loader if you want to specify an inline component, that is one that is not defined in a dedicated QML file but using the Component element.

QSS properties for custom widget: How to implement hover and pressed states

I found this example on the web on how to implement custom properties accessible from QSS for custom QWidgets: https://qt-project.org/wiki/Qt_Style_Sheets_and_Custom_Painting_Example
Does anyone know how can I implement the widget so that I can have different colors for hover or pressed states?
Current stylesheet looks like this:
SWidget
{
qproperty-lineColor: yellow;
qproperty-rectColor: red;
}
I want to be able to have something like this:
SWidget:hover
{
qproperty-lineColor: blue;
qproperty-rectColor: green;
}
SWidget:pressed
{
qproperty-lineColor: orange;
qproperty-rectColor: violet;
}
Note: I know it is possible to implement mouse events and change the colors using qproperties specific to the mouse events, for example:
SWidget
{
qproperty-lineColor: yellow;
qproperty-rectColor: red;
qproperty-lineColor-hover: orange;
qproperty-rectColor-hover: violet;
}
but I would like to be able to make it work using the original qss/css way.
Regards!
When user hover or pressed widget, you should change some widget property. And make different QSS selector for that properties.
After change property you should make unpolish\polish of application styles.
qApp->style()->unpolish( this );
qApp->style()->polish( this );
Where "this" current window pointer. That "magic" code will help to have affect of appropriate QSS selector.

CSS selector for custom Qt class

I created a "Slider" subclass of QWidget and would like to be able to style it with Qt's stylesheets. Is there a way to declare the widget to Qt application so that this setting in the application stylesheet is applied to all sliders ?
Slider { background-color:blue; }
Or if this is not possible, can I use a class like this ?
QWidget.slider { background-color:blue; }
The widgets have a "className()" method that is accessible via the meta object. In my case this is:
slider.metaObject()->className();
// ==> mimas::Slider
Since the "Slider" class is in a namespace, you have to use the fully qualified name for styling (replacing '::' with '--'):
mimas--Slider { background-color:blue; }
Another solution is to define a class property and use it with a leading dot:
.slider { background-color:blue; }
C++ Slider class:
Q_PROPERTY(QString class READ cssClass)
...
QString cssClass() { return QString("slider"); }
While on the subject, to draw the slider with colors and styles defined in CSS, this is how you get them (link text):
// background-color:
palette.color(QPalette::Window)
// color:
palette.color(QPalette::WindowText)
// border-width:
// not possible (too bad...). To make it work, you would need to copy paste
// some headers defined in qstylesheetstyle.cpp for QRenderRule class inside,
// get the private headers for QStyleSheetStyle and change them so you can call
// renderRule and then you could use the rule to get the width borders. But your
// code won't link because the symbol for QStyleSheetStyle are local in QtGui.
// The official and supported solution is to use property:
// qproperty-border:
border_width_ // or whatever stores the Q_PROPERTY border
And finally, a note on QPalette values from CSS:
color = QPalette::WindowText
background = QPalette::Window
alternate-background-color = QPalette::AlternateBase
selection-background-color = QPalette::Highlighted
selection-color = QPalette::HighlightedText

Resources