5

I'm trying to design a synoptic panel in Qt-QML (for desktop). The interface should be used with fixed resolution, so I prefer to use PNG images for different graphical elements to create schema (pipe, pipe-curve, pipe-t, pump, valve, etc.). Now the problem is how to change fill color of different components: I'd like that user can choise the color (in real case scenario there are different liquid that can be used), but I cannot find how do that in QML. I thinked to use my PNG components as background, and then drawing a Rectangle over, masked by a SVG mask.. But on the web I can find only qt-components "MaskedItem" not available for desktop. I'm wondering if there's no way to put over my PNG an SVG image with one color (black and transparent), and then change color's property of this in QML. Anybody have got any ideas? Thanks really much.

(EDIT better explain)

The problem is more complicated than I can be able to explain. I have created several QML components with specific properties, each component has a background image (PNG) with transparency. Now, what I need is fill a defined area of PNG image using a variable color "x", when the main QML is in a particular state (setted by Qt application). My problem was: how to fill the area of a PNG/SVG with a variable color, from QML? What I need is placing my "background" image, then apply over this a "Rectangle" component (color "x"), and finally put a mask on this Rectangle, to define what area of this must be visible, preserving the background (the bottom image of before). I hope I explained myself better now.

(EDIT solution) After a lot of hours, I was not able to find any other solutions than using qt-components MaskedItem. Below i have posted solution I used. Thank to you all for interest.

deste
  • 542
  • 1
  • 5
  • 17
  • 1
    It can be achieved very efficiently through using a shader effect: http://stackoverflow.com/questions/39903639/how-to-apply-opacity-mask-to-a-qml-item?noredirect=1&lq=1 – dtech Nov 26 '16 at 16:42

4 Answers4

3

The only solution found is to use "qt-components MaskedItem"; it must be taken from repository and it must compile under Qt desktop. Now is possible to use MaskedItem in any QML component of synoptic. The QML code of components will be something like this:

Item
{
    id: arrow
    property int  rotate: 0
    property bool active: false
    width: 32
    height: 32
    clip: true

    Image {
        smooth: true
        source: {
            if(rotate==90)
                "../res/arrow_1_bg.png"
            else if(rotate==180)
                "../res/arrow_2_bg.png"
            else if(rotate==270)
                "../res/arrow_3_bg.png"
            else
                "../res/arrow_0_bg.png"
        }
    }

    MaskedItem
    {
        visible: active
        anchors.fill: parent
        mask: Image
        {
            anchors.fill: parent
            smooth: true
            source: {
                if(rotate==90)
                    "../res/arrow_1_mask.png"
                else if(rotate==180)
                    "../res/arrow_2_mask.png"
                else if(rotate==270)
                    "../res/arrow_3_mask.png"
                else
                    "../res/arrow_0_mask.png"
            }
        }
        Rectangle
        {
            anchors.fill: parent
            color: active_color
            opacity: .6
        }
    }

} // Item: arrow

'active' property means if component must be "filled" or not, using global property "active_color" defined in the main QML.

So, all components (pipes, pipes angle, arrows, pumps, valves, etc.) have got a background image (PNG) with transparency. Pipes (that have the "orientation" property, horizontal or vertical) are PNG 1x32px streched. An example of final screen can be something like this:

example1 http://imageshack.us/a/img9/2968/example1c.png.

All the components have also a MaskedItem, the mask image is used for define the visible area of a Rectangle (with color "x"), place over the main component's background image. An example of 2 components background and mask images:

example3 http://imageshack.us/a/img442/9863/example3y.png.

The final result, if the 'active' property is true and the chosen color is green, can be something like this:

example2 http://imageshack.us/a/img836/1968/example2c.png.

deste
  • 542
  • 1
  • 5
  • 17
1

I found a weird solution to this problem by using the icon property. e.g.

Item {
    width: 256
    height: 256
    Button {
        anchors.centerIn: parent
        background: Item { }
        icon.source: "https://raw.githubusercontent.com/Esri/calcite-ui-icons/master/icons/biking-32.svg"
        icon.width: 256
        icon.height: 256
        icon.color: "blue"
        enabled: false
    }
}

Which renders my biking-32.svg at 256x256 resolution in blue:

biking-32.svg rendered at 256x256 in blue

Things of note:

  • Not every QML component supports an icon property
  • Not every QML component reacts to the color in icon.color consistently
  • The Button has much larger dimensions than the icon so, we use anchors.centerIn: parent and host it inside an Item to crop most of the unused Button surrounds
  • background: Item { } is used to disable much of the default Button rendering
  • enabled: false is used to disable the button's default behavior of reacting to mouse clicks
Stephen Quan
  • 21,481
  • 4
  • 88
  • 75
0

Both PNG and SVG images support alpha channel (i.e. transparency), so, why don't you just put your SVG (with transparent parts where you wanto to see your background) over your PNG background?

Or even the other way around... you could put you PNG parts (with transparent "holes") over your SVG image.

TheHuge_
  • 1,039
  • 17
  • 29
  • Thanks for your tips TheHuge But first I have not explained the problem correctly. I found a solution in the meantime and updated the question. Thank you again, anyway! – deste Mar 06 '13 at 12:33
0

I had the same problem, and ended up creating a custom image renderer that took an optional color parameter as part of the image source string, then replaced the original color before rendering. Seemed more efficient than rendering an image just to render it again.

Evan
  • 2,441
  • 23
  • 36