QtQuick ToolTip Component
[toc align_right="yes" depth="3"]
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":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:
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":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):
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."
}