3

changing the style of a component, seems to replace all the features of the default style. is there a way to change only one feature?

For example, suppose i want a red button;

import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4

ApplicationWindow
{
    visible: true
    width: 640
    height: 480

    Button
    {
        height: 200
        width: 200
        text: "Press me"
        style: ButtonStyle 
        {
            // changes background but also throws away everything else
            // in standard button style
            background: Rectangle { color: "red" }
        }
    }
}

re-defining ButtonStyle with a background works fine for changing the color of the button, but then everything else within the system default ButtonStyle is gone. For example, the border and the click highlight.

How to just change one feature and keep the rest?

Sorry if this has been asked before.

thanks,

Update

The above question was for Controls 1, but the same problem exists for Controls 2. Here's the same example code for Controls 2.

import QtQuick 2.7
import QtQuick.Controls 2.1

ApplicationWindow
{
    visible: true
    width: 640
    height: 480

    Button
    {
        height: 200
        width: 200
        text: "Press me"

        // changes background but also throws away everything else
        // in standard button style
        background: Rectangle { color: "red" }
    }
}
jkj yuio
  • 2,543
  • 5
  • 32
  • 49

2 Answers2

2

Preface
The purpose of QtQuick.Controls 1.4 was, to offer controls with native look and feel. If you want to have easier adjustable controls, and don't need the native look, you should consider the newer and faster QtQuick.Controls 2.0.

Main
What you desire is - afaik - impossible, as the default style consists out of two Rectangles and one Image where the Image seems to be the most important. You can find the images in the mingw-package at this location:

Qt\Qt5.7.0\5.7\mingw53_32\qml\QtQuick\Controls\Styles\Base\images

To access the objects of the control, you find them here:

    Button {
        id: but2
        x: 50
        onClicked: console.log(this.children[1].item.children[0].item.children[0], this.children[1].item.children[0].item.children[1], this.children[1].item.children[0].item.children[2])
    }

So, the easiest solution, to pop into my mind is to use Colorize

import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtGraphicalEffects 1.0
Window {
    width: 1024
    height: 800
    visible: true

    Button {
        id: but
        text: 'test'
    }
    Colorize {
        source: but
        anchors.fill: but

        // values from the documentation example.
        hue: 0.0
        saturation: 0.5
        lightness: -0.2
    }
}

Or to be more general: To just adjust the styling, go for shaders.

QtQuick.Controls 2.0
There you have another case: the background is a Rectangle not just the Component. But if you do not assign one your self, it is only created after the Button.

Button {
    id: but1
    background.color: 'red'
}

is impossible, as the background is not instantiated when you try to assign the color.
You could use the Component.onCompleted handler to do this:

Button {
    id: but1   
    Component.onCompleted: background.color = 'red'
}

But of course you overwrite the Binding of the original style, that handles the color-change while the Button is beeing pressed

Button {
    id: but1   
    Component.onCompleted: background.color = Qt.binding(function() { return (but1.pressed ? 'red' : 'green') }
}

would enable the color-change again, but you won't have the original color. You might retrive the orignal color by trying it out:

Button {
    id: but1
    onPressed: console.log(this.background.color)
    onReleased: console.log(this.background.color)
}

This will output you the colors of the two states for pressed. But maybe there are more! So the easiest solution is to use a conditional Binding as this:

Button {
    id: but1
}

Binding {
    when: but1.pressed
    target: but1
    property: 'background.color'
    value: 'red'
}
  • bugger. sorry yes, i am supposed to be using Controls2.Button. I changed to this, but it's the same except `Label` -> `contentItem`. Then i have the same problem, whenever i override, say `background`. I like your ideas about shaders and `Colorize`. I think it's a better way to add style than change these properties. FWIW, i think the properties are bad design if you can't somehow inherit the original. thanks. I'll go with your suggestions. – jkj yuio Mar 12 '17 at 01:00
  • 1
    Please update your question to reflect what you're actually using. They are two very different styling APIs. – Mitch Mar 12 '17 at 08:17
  • Though I already updated the answer to adress some posibilities you have with the `QtQuick.Controls 2.x` it would be good, to update the question, to match, so it can help others aswell. Futher please do not forget to accept the answer if it contains what you were looking for. Please do so as well, for all the answers to your other questions, for this is both: polite to the people who took the time to answer, and to help people find the answer, if they have the same problem as you. – derM - not here for BOT dreams Mar 13 '17 at 19:59
  • @derM. I appreciate your answers, but this question is not answered. Changing simple properties of Controls 2 styles, seems either impossible or _extremely_ complex. I am having similar problems with other C2's; for example `CheckBox`. How to change the color of the checkmark. Whenever i read the implementation QML, it uses some private feature, so it's not just a matter of copying it. – jkj yuio Apr 20 '17 at 23:40
  • I can't see your problem. `cb` is my `CheckBox`. I want to change the color of the indicator to red, when it is checked. I use: `Binding { when: cb.checkState === Qt.Checked; target: cb.indicator; property: 'color'; value: 'red' }`. No instantiation of a privat class involved. The only thing about this `indicator` is, that it is only instantiated uppon completion of the `CheckBox` to make it more memory efficient. (There can be hundreds of `CheckBox`s – derM - not here for BOT dreams Apr 22 '17 at 10:17
  • The `QtQuick.Controls 2.x` have tons of different controls. There are some recipes they follow for their styling, but they are still diffreent controls, so there are different needs to them. I can't give you an explaination on how to change every single property of every single control. I can give you a general overview. If you have more specific questions, because you are stuck with e.g. the `CheckBox`, ask a new question, where you ask for a specific styling. Then we can look into it, and see if and how it is doable. – derM - not here for BOT dreams Apr 22 '17 at 10:26
0

All QC2 types that derive from a Control have a member called palette. (See here) For some reason they don't mention this in the docs when they're describing how to customize the different controls. But you can look in the source code to see which palette colors you need to modify for your object. For instance, to change a Button's background to be red, you just need this:

Button
{
    id: btn1
    palette.button: "red"
}

You can change all buttons in your application by changing the palette in your ApplicationWindow, like this:

ApplicationWindow
{
    id: mainWin

    // Change default button background to be red
    palette.button: "red"

    Button
    {
        id: btn1
        // Background will be red
    }

    Button
    {
        id: btn2

        // You can of course override the default 
        palette.button: "green"
    }
}
JarMan
  • 7,589
  • 1
  • 10
  • 25