QtQuick ToolTip Component

From Qt Wiki
Revision as of 12:47, 24 March 2016 by Wieland (talk | contribs) (clean-up)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search


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."
}