QtQuick ToolTip Component: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
(clean-up)
 
(5 intermediate revisions by 3 users not shown)
Line 1: Line 1:
[[Category:Developing_with_Qt::Qt Quick]]<br />[toc align_right=&quot;yes&amp;quot; depth=&quot;3&amp;quot;]
[[Category:Developing_with_Qt::Qt Quick]]


= Qt Quick ToolTip component =
= Qt Quick ToolTip component =
Line 11: Line 11:
== The first sample of ToolTip ==
== The first sample of ToolTip ==


The first implementation looks like a standard tooltip and you can create it from JavaScript. The author of this code is &quot;Xander84&amp;quot;:http://qt.io/member/7754 This tooltip has a show and hide function to fade it in and out respectively, by default it will destroy itself after it's hidden (the destroyOnHide property can be set to false if you don't want that). The code looks like:
The first implementation looks like a standard tooltip and you can create it from JavaScript. The author of this code is [http://forum.qt.io/user/xander84 Xander84] This tooltip has a show and hide function to fade it in and out respectively, by default it will destroy itself after it's hidden (the destroyOnHide property can be set to false if you don't want that). The code looks like:


<code><br />import QtQuick 2.2
<code>
import QtQuick 2.2


Rectangle {<br /> id: tooltip
Rectangle {
id: tooltip


property alias text: tooltipText.text<br /> property alias textItem: tooltipText<br /> property int fadeInDelay: 500<br /> property int fadeOutDelay: 500<br /> property bool autoHide: true<br /> property alias autoHideDelay: hideTimer.interval<br /> property bool destroyOnHide: true
property alias text: tooltipText.text
property alias textItem: tooltipText
property int fadeInDelay: 500
property int fadeOutDelay: 500
property bool autoHide: true
property alias autoHideDelay: hideTimer.interval
property bool destroyOnHide: true


function show() {<br /> state = &quot;showing&amp;quot;<br /> if (hideTimer.running) {<br /> hideTimer.restart()<br /> }<br /> }
function show() {
state = "showing"
if (hideTimer.running) {
hideTimer.restart()
}
}


function hide() {<br /> if (hideTimer.running) {<br /> hideTimer.stop()<br /> }<br /> state = &quot;hidden&amp;quot;<br /> }
function hide() {
if (hideTimer.running) {
hideTimer.stop()
}
state = "hidden"
}


width: tooltipText.width + 20<br /> height: tooltipText.height + 10<br /> color: &quot;#dd000000&amp;quot;<br /> radius: 6<br /> opacity: 0
width: tooltipText.width + 20
height: tooltipText.height + 10
color: "#dd000000"
radius: 6
opacity: 0


Text {<br /> id: tooltipText<br /> anchors.centerIn: parent<br /> horizontalAlignment: Text.AlignHCenter<br /> color: &quot;white&amp;quot;<br /> font.pointSize: 10<br /> font.bold: true<br /> }
Text {
id: tooltipText
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
color: "white"
font.pointSize: 10
font.bold: true
}


MouseArea {<br /> anchors.fill: parent<br /> onClicked: hide()<br /> }
MouseArea {
anchors.fill: parent
onClicked: hide()
}


Timer {<br /> id: hideTimer<br /> interval: 5000<br /> onTriggered: hide()<br /> }
Timer {
id: hideTimer
interval: 5000
onTriggered: hide()
}


states: [<br /> State {<br /> name: &quot;showing&amp;quot;<br /> PropertyChanges { target: tooltip; opacity: 1 }<br /> onCompleted: {<br /> if (autoHide) {<br /> hideTimer.start()<br /> }<br /> }<br /> },<br /> State {<br /> name: &quot;hidden&amp;quot;<br /> PropertyChanges { target: tooltip; opacity: 0 }<br /> onCompleted: {<br /> if (destroyOnHide) {<br /> tooltip.destroy()<br /> }<br /> }<br /> }<br /> ]
states: [
State {
name: "showing"
PropertyChanges { target: tooltip; opacity: 1 }
onCompleted: {
if (autoHide) {
hideTimer.start()
}
}
},
State {
name: "hidden"
PropertyChanges { target: tooltip; opacity: 0 }
onCompleted: {
if (destroyOnHide) {
tooltip.destroy()
}
}
}
]


transitions: [<br /> Transition {<br /> to: &quot;showing&amp;quot;<br /> NumberAnimation { target: tooltip; property: &quot;opacity&amp;quot;; duration: fadeInDelay }<br /> },<br /> Transition {<br /> to: &quot;hidden&amp;quot;<br /> NumberAnimation { target: tooltip; property: &quot;opacity&amp;quot;; duration: fadeOutDelay }<br /> }<br /> ]<br />}<br /></code>
transitions: [
Transition {
to: "showing"
NumberAnimation { target: tooltip; property: "opacity"; duration: fadeInDelay }
},
Transition {
to: "hidden"
NumberAnimation { target: tooltip; property: "opacity"; duration: fadeOutDelay }
}
]
}
</code>


Also this component has a simple JavaScript file to make it a little easier to create tooltips. This script looks like (TooltipCreator.js):
Also this component has a simple JavaScript file to make it a little easier to create tooltips. This script looks like (TooltipCreator.js):


<code><br />var component = Qt.createComponent(&quot;Tooltip.qml&amp;quot;);
<code>
var component = Qt.createComponent("Tooltip.qml");


function create(text, parent, properties) {<br /> if (typeof properties = &amp;quot;undefined&amp;quot;) &amp;#123;
function create(text, parent, properties) {
         properties = &amp;#123;
if (typeof properties = "undefined") {
             anchors: &amp;#123;
         properties = {
             anchors: {
                 horizontalCenter: parent.horizontalCenter,
                 horizontalCenter: parent.horizontalCenter,
                 bottom: parent.bottom,
                 bottom: parent.bottom,
                 bottomMargin: parent.height / 8
                 bottomMargin: parent.height / 8
             &amp;#125;
             }
         &amp;#125;;
         };
     &amp;#125;
     }
     properties.text = text;
     properties.text = text;
     var tooltip = component.createObject(parent, properties);
     var tooltip = component.createObject(parent, properties);
     if (tooltip = null) {<br /> console.error(&quot;error creating tooltip: &quot; + component.errorString());<br /> } else if (properties.anchors) {<br /> // manual anchor mapping necessary<br /> for (var anchor in properties.anchors) {<br /> tooltip.anchors[anchor] = properties.anchors[anchor];<br /> }<br /> }<br /> return tooltip;<br />}<br /></code>
     if (tooltip = null) {
console.error("error creating tooltip: " + component.errorString());
} else if (properties.anchors) {
// manual anchor mapping necessary
for (var anchor in properties.anchors) {
tooltip.anchors[anchor] = properties.anchors[anchor];
}
}
return tooltip;
}
</code>


=== How to use? ===
=== How to use? ===
Line 56: Line 134:
All you need to do is importing the JavaScript file and call a command from it.
All you need to do is importing the JavaScript file and call a command from it.


<code><br />import &quot;TooltipCreator.js&amp;quot; as TooltipCreator<br /><br />TooltipCreator.create(&quot;text on the tooltip&amp;quot;, parentItem).show()<br /></code>
<code>
import "TooltipCreator.js" as TooltipCreator
TooltipCreator.create("text on the tooltip", parentItem).show()
</code>


By default it will fade in, stay visible for 5 seconds and than fade out and destroy itself, the user can click on the tooltip to hide it immediately, also it will be anchored at the bottom center of the provided parent Item (see the TooltipCreator.js).
By default it will fade in, stay visible for 5 seconds and than fade out and destroy itself, the user can click on the tooltip to hide it immediately, also it will be anchored at the bottom center of the provided parent Item (see the TooltipCreator.js).
Line 62: Line 144:
The 3rd optional argument can be used to specify custom properties for the tooltip, e.g.
The 3rd optional argument can be used to specify custom properties for the tooltip, e.g.


<code><br />TooltipCreator.create(&quot;absolute positioned tooltip&amp;quot;), rootItem, { x: 100, y: 50 }).show()<br /></code>
<code>
TooltipCreator.create("absolute positioned tooltip"), rootItem, { x: 100, y: 50 }).show()
</code>


or set the properties on the item directly
or set the properties on the item directly


<code><br />var tooltip = TooltipCreator.create(qsTr(&quot;Network Error!check your network connection\nor try again later.&quot;), mainView)<br />tooltip.color = &quot;#ddff0000&amp;quot;<br />tooltip.textItem.color = &quot;white&amp;quot;<br />tooltip.show()<br /></code>
<code>
var tooltip = TooltipCreator.create(qsTr("Network Error!check your network connection\nor try again later."), mainView)
tooltip.color = "#ddff0000"
tooltip.textItem.color = "white"
tooltip.show()
</code>


== The second sample of ToolTip. ==
== The second sample of ToolTip. ==


The second implementation looks like a label which show near mouse on the component where it need to be shown. The author of this code is &quot;shav&amp;quot;:http://qt.io/member/4674 This component has less dynamic properties for the customisation than the first embodiment. The main difference of this implementation in that the label shown near with mouse and if user moving mouse on the component the label moving with mouse. The code looks like (ToolTip.qml):
The second implementation looks like a label which show near mouse on the component where it need to be shown. The author of this code is [http://qt.io/member/4674 shav] This component has less dynamic properties for the customisation than the first embodiment. The main difference of this implementation in that the label shown near with mouse and if user moving mouse on the component the label moving with mouse. The code looks like (ToolTip.qml):


<code><br />import QtQuick 2.0<br />import QtQuick.Controls 1.1<br />import QtGraphicalEffects 1.0
<code>
import QtQuick 2.0
import QtQuick.Controls 1.1
import QtGraphicalEffects 1.0


Item {<br /> id: toolTipRoot<br /> width: toolTip.contentWidth<br /> height: toolTipContainer.height<br /> visible: false<br /> clip: false<br /> z: 999999999
Item {
id: toolTipRoot
width: toolTip.contentWidth
height: toolTipContainer.height
visible: false
clip: false
z: 999999999


property alias text: toolTip.text<br /> property alias radius: content.radius<br /> property alias backgroundColor: content.color<br /> property alias textColor: toolTip.color<br /> property alias font: toolTip.font<br /> property var target: null
property alias text: toolTip.text
property alias radius: content.radius
property alias backgroundColor: content.color
property alias textColor: toolTip.color
property alias font: toolTip.font
property var target: null


function onMouseHover(x, y)<br /> {<br /> var obj = toolTipRoot.target.mapToItem(toolTipRoot.parent, x, y);<br /> toolTipRoot.x = obj.x;<br /> toolTipRoot.y = obj.y + 5;<br /> }
function onMouseHover(x, y)
{
var obj = toolTipRoot.target.mapToItem(toolTipRoot.parent, x, y);
toolTipRoot.x = obj.x;
toolTipRoot.y = obj.y + 5;
}


function onVisibleStatus(flag)<br /> {<br /> toolTipRoot.visible = flag;<br /> }
function onVisibleStatus(flag)
{
toolTipRoot.visible = flag;
}


Component.onCompleted: {<br /> var itemParent = toolTipRoot.target;
Component.onCompleted: {
var itemParent = toolTipRoot.target;


var newObject = Qt.createQmlObject('import QtQuick 2.0; MouseArea {signal mouserHover(int x, int y); signal showChanged(bool flag); anchors.fill:parent; hoverEnabled: true; onPositionChanged: {mouserHover(mouseX, mouseY)} onEntered: {showChanged(true)} onExited:{showChanged(false)} onClicked:{parent.focus = true}}',<br /> itemParent, &quot;mouseItem&amp;quot;);<br /> newObject.mouserHover.connect(onMouseHover);<br /> newObject.showChanged.connect(onVisibleStatus);<br /> }
var newObject = Qt.createQmlObject('import QtQuick 2.0; MouseArea {signal mouserHover(int x, int y); signal showChanged(bool flag); anchors.fill:parent; hoverEnabled: true; onPositionChanged: {mouserHover(mouseX, mouseY)} onEntered: {showChanged(true)} onExited:{showChanged(false)} onClicked:{parent.focus = true}}',
itemParent, "mouseItem");
newObject.mouserHover.connect(onMouseHover);
newObject.showChanged.connect(onVisibleStatus);
}


Item {<br /> id: toolTipContainer<br /> z: toolTipRoot.z + 1<br /> width: content.width + (2*toolTipShadow.radius)<br /> height: content.height + (2*toolTipShadow.radius)
Item {
id: toolTipContainer
z: toolTipRoot.z + 1
width: content.width + (2*toolTipShadow.radius)
height: content.height + (2*toolTipShadow.radius)


Rectangle {<br /> id: content<br /> anchors.centerIn: parent<br /> width: toolTipRoot.width<br /> height: toolTip.contentHeight + 10<br /> radius: 3
Rectangle {
id: content
anchors.centerIn: parent
width: toolTipRoot.width
height: toolTip.contentHeight + 10
radius: 3


Text {<br /> id: toolTip<br /> anchors {fill: parent; margins: 5}<br /> wrapMode: Text.WrapAnywhere<br /> }<br /> }<br /> }
Text {
id: toolTip
anchors {fill: parent; margins: 5}
wrapMode: Text.WrapAnywhere
}
}
}


DropShadow {<br /> id: toolTipShadow<br /> z: toolTipRoot.z + 1<br /> anchors.fill: source<br /> cached: true<br /> horizontalOffset: 4<br /> verticalOffset: 4<br /> radius: 8.0<br /> samples: 16<br /> color: &quot;#80000000&amp;quot;<br /> smooth: true<br /> source: toolTipContainer<br /> }
DropShadow {
id: toolTipShadow
z: toolTipRoot.z + 1
anchors.fill: source
cached: true
horizontalOffset: 4
verticalOffset: 4
radius: 8.0
samples: 16
color: "#80000000"
smooth: true
source: toolTipContainer
}


Behavior on visible { NumberAnimation { duration: 200 }}<br />}<br /></code>
Behavior on visible { NumberAnimation { duration: 200 }}
}
</code>


This component can be created in QML and from JavaScript. You can change a few properties:
This component can be created in QML and from JavaScript. You can change a few properties:
Line 109: Line 254:
Create a new item with name ToolTip in component where you want to show tooltip. I recommend to add it to the root component. This component has a default width in 150px. The height will calculate automatically using the text. The simple code to use look like:
Create a new item with name ToolTip in component where you want to show tooltip. I recommend to add it to the root component. This component has a default width in 150px. The height will calculate automatically using the text. The simple code to use look like:


<code><br /> ToolTip {<br /> id: tooltip1<br /> width: 200<br /> target: id_of_component<br /> text: &quot;Enter the text here.&quot;<br /> }
<code>
ToolTip {
id: tooltip1
width: 200
target: id_of_component
text: "Enter the text here."
}

Latest revision as of 12:47, 24 March 2016


Qt Quick ToolTip component

This article will give you a simple component to use a ToolTip in your QML applications. As you know in first version of Qt Quick Components (the first version has a different name ‘QML Desktop Component 1.0’) has a special component which gives developers to add ToolTip to any components (Rectangle, Item, Label, etc.). But in last version of Qt Quick Controls this component was removed. Really I don’t know why this happened but I think in future releases this small issue will be fix and we all get the nice component which we will use in our projects.

But while this will happen I think the most of you faced with situation when you need to show the information of UI element but can't add the Label because the designer doesn't provide any labels. In some UI component you can use the placeholder (TextField) but in most components you don't have any properties to set a label on a component. In this situation you need to add the label or insert your component to GroupBox which has the title property. But it is not always convenient.

This page is shows you two components which you can use as a ToolTip.

The first sample of ToolTip

The first implementation looks like a standard tooltip and you can create it from JavaScript. The author of this code is Xander84 This tooltip has a show and hide function to fade it in and out respectively, by default it will destroy itself after it's hidden (the destroyOnHide property can be set to false if you don't want that). The code looks like:

import QtQuick 2.2

Rectangle {
 id: tooltip

property alias text: tooltipText.text
 property alias textItem: tooltipText
 property int fadeInDelay: 500
 property int fadeOutDelay: 500
 property bool autoHide: true
 property alias autoHideDelay: hideTimer.interval
 property bool destroyOnHide: true

function show() {
 state = "showing"
 if (hideTimer.running) {
 hideTimer.restart()
 }
 }

function hide() {
 if (hideTimer.running) {
 hideTimer.stop()
 }
 state = "hidden"
 }

width: tooltipText.width + 20
 height: tooltipText.height + 10
 color: "#dd000000"
 radius: 6
 opacity: 0

Text {
 id: tooltipText
 anchors.centerIn: parent
 horizontalAlignment: Text.AlignHCenter
 color: "white"
 font.pointSize: 10
 font.bold: true
 }

MouseArea {
 anchors.fill: parent
 onClicked: hide()
 }

Timer {
 id: hideTimer
 interval: 5000
 onTriggered: hide()
 }

states: [
 State {
 name: "showing"
 PropertyChanges { target: tooltip; opacity: 1 }
 onCompleted: {
 if (autoHide) {
 hideTimer.start()
 }
 }
 },
 State {
 name: "hidden"
 PropertyChanges { target: tooltip; opacity: 0 }
 onCompleted: {
 if (destroyOnHide) {
 tooltip.destroy()
 }
 }
 }
 ]

transitions: [
 Transition {
 to: "showing"
 NumberAnimation { target: tooltip; property: "opacity"; duration: fadeInDelay }
 },
 Transition {
 to: "hidden"
 NumberAnimation { target: tooltip; property: "opacity"; duration: fadeOutDelay }
 }
 ]
}

Also this component has a simple JavaScript file to make it a little easier to create tooltips. This script looks like (TooltipCreator.js):

var component = Qt.createComponent("Tooltip.qml");

function create(text, parent, properties) {
 if (typeof properties = "undefined") {
        properties = {
            anchors: {
                horizontalCenter: parent.horizontalCenter,
                bottom: parent.bottom,
                bottomMargin: parent.height / 8
            }
        };
    }
    properties.text = text;
    var tooltip = component.createObject(parent, properties);
    if (tooltip = null) {
 console.error("error creating tooltip: " + component.errorString());
 } else if (properties.anchors) {
 // manual anchor mapping necessary
 for (var anchor in properties.anchors) {
 tooltip.anchors[anchor] = properties.anchors[anchor];
 }
 }
 return tooltip;
}

How to use?

All you need to do is importing the JavaScript file and call a command from it.

import "TooltipCreator.js" as TooltipCreator

TooltipCreator.create("text on the tooltip", parentItem).show()

By default it will fade in, stay visible for 5 seconds and than fade out and destroy itself, the user can click on the tooltip to hide it immediately, also it will be anchored at the bottom center of the provided parent Item (see the TooltipCreator.js).

The 3rd optional argument can be used to specify custom properties for the tooltip, e.g.

TooltipCreator.create("absolute positioned tooltip"), rootItem, { x: 100, y: 50 }).show()

or set the properties on the item directly

var tooltip = TooltipCreator.create(qsTr("Network Error!check your network connection\nor try again later."), mainView)
tooltip.color = "#ddff0000"
tooltip.textItem.color = "white"
tooltip.show()

The second sample of ToolTip.

The second implementation looks like a label which show near mouse on the component where it need to be shown. The author of this code is shav This component has less dynamic properties for the customisation than the first embodiment. The main difference of this implementation in that the label shown near with mouse and if user moving mouse on the component the label moving with mouse. The code looks like (ToolTip.qml):

import QtQuick 2.0
import QtQuick.Controls 1.1
import QtGraphicalEffects 1.0

Item {
 id: toolTipRoot
 width: toolTip.contentWidth
 height: toolTipContainer.height
 visible: false
 clip: false
 z: 999999999

property alias text: toolTip.text
 property alias radius: content.radius
 property alias backgroundColor: content.color
 property alias textColor: toolTip.color
 property alias font: toolTip.font
 property var target: null

function onMouseHover(x, y)
 {
 var obj = toolTipRoot.target.mapToItem(toolTipRoot.parent, x, y);
 toolTipRoot.x = obj.x;
 toolTipRoot.y = obj.y + 5;
 }

function onVisibleStatus(flag)
 {
 toolTipRoot.visible = flag;
 }

Component.onCompleted: {
 var itemParent = toolTipRoot.target;

var newObject = Qt.createQmlObject('import QtQuick 2.0; MouseArea {signal mouserHover(int x, int y); signal showChanged(bool flag); anchors.fill:parent; hoverEnabled: true; onPositionChanged: {mouserHover(mouseX, mouseY)} onEntered: {showChanged(true)} onExited:{showChanged(false)} onClicked:{parent.focus = true}}',
 itemParent, "mouseItem");
 newObject.mouserHover.connect(onMouseHover);
 newObject.showChanged.connect(onVisibleStatus);
 }

Item {
 id: toolTipContainer
 z: toolTipRoot.z + 1
 width: content.width + (2*toolTipShadow.radius)
 height: content.height + (2*toolTipShadow.radius)

Rectangle {
 id: content
 anchors.centerIn: parent
 width: toolTipRoot.width
 height: toolTip.contentHeight + 10
 radius: 3

Text {
 id: toolTip
 anchors {fill: parent; margins: 5}
 wrapMode: Text.WrapAnywhere
 }
 }
 }

DropShadow {
 id: toolTipShadow
 z: toolTipRoot.z + 1
 anchors.fill: source
 cached: true
 horizontalOffset: 4
 verticalOffset: 4
 radius: 8.0
 samples: 16
 color: "#80000000"
 smooth: true
 source: toolTipContainer
 }

Behavior on visible { NumberAnimation { duration: 200 }}
}

This component can be created in QML and from JavaScript. You can change a few properties:

  • text The text of tooltip.
  • radius The corner radius.
  • backgroundColor The background color.
  • textColor The text color.
  • font The font settings to set custom font of text.
  • target The component on which need to show tooltip.

How to use?

Create a new item with name ToolTip in component where you want to show tooltip. I recommend to add it to the root component. This component has a default width in 150px. The height will calculate automatically using the text. The simple code to use look like:

ToolTip {
id: tooltip1
width: 200
target: id_of_component
text: "Enter the text here."
}