ToolTip是一个较为常用的组件,一般有两种使用方式,直接创建组件或者用附加属性:
Text{
text: "..."
anchors.centerIn: parent
//附加属性的方式
ToolTip.text: "..."
ToolTip.visible: mouse.containsMouse
//直接创建组件
ToolTip{
id: tip
text: "..."
visible: !mouse.containsMouse
}
}
如果是直接创建组件,那很容易就可以替换为自定义的ToolTip,换个组件名就行了。如果想修改附加属性的样式就有问题了,直接把ToolTip替换为自定义的组件名的话,那么显示出来的效果还是默认的ToolTip 。
我们可以从源码中找到问题的根源(E:\Qt\qt-everywhere-src-5.15.2\qtquickcontrols2\src\quicktemplates2\qquicktooltip.cpp):
QQuickToolTip *QQuickToolTipAttachedPrivate::instance(bool create) const
{
QQmlEngine *engine = qmlEngine(parent);
if (!engine)
return nullptr;
static const char *name = "_q_QQuickToolTip";
QQuickToolTip *tip = engine->property(name).value();
if (!tip && create) {
// TODO: a cleaner way to create the instance? QQml(Meta)Type?
QQmlComponent component(engine);
component.setData("import QtQuick.Controls 2.4; ToolTip { }", QUrl());
QObject *object = component.create();
if (object)
object->setParent(engine);
tip = qobject_cast(object);
if (!tip)
delete object;
else
engine->setProperty(name, QVariant::fromValue(object));
}
return tip;
}
可以看到,附加属性中这个ToolTip的创建是写死的,并以动态属性的方式保存在engine对象。要改样式只有两种方式:创建同名组件(定义记得带限定符,如T.ToolTip),或者修改源码设置的Property。
如果创建同名组件,那可能有些地方会写漏导致没覆盖掉,所以我认为修改源码设置的Property是更好的方法。
下面是我的测试效果:
GitHub链接:https://github.com/gongjianbo/MyTestCode/tree/master/Qml/TestQml_20210303_ToolTip
完整代码如下(main.cpp+BasicToolTip.qml+main.qml三个文件):
#include
#include
#include
#include
void updateToolTip(QQmlApplicationEngine *engine);
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
updateToolTip(&engine);
return app.exec();
}
void updateToolTip(QQmlApplicationEngine *engine)
{
//替换默认的ToolTip附加属性样式
static const char *name = "_q_QQuickToolTip";
QQmlComponent *component = new QQmlComponent(engine,QUrl("qrc:/BasicToolTip.qml"),qApp);
auto create_func = [component,engine]{
if(component->isError()){
qWarning() isReady()){
QObject *object = component->create();
if (object){
object->setParent(engine);
engine->setProperty(name, QVariant::fromValue(object));
}
}
};
if(component->isLoading()){
QObject::connect(component,&QQmlComponent::statusChanged,create_func);
}else{
create_func();
}
}
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls.impl 2.12
import QtQuick.Templates 2.12 as T
T.ToolTip {
id: control
x: parent ? Number.parseInt((parent.width - implicitWidth) / 2) : 0
y: -implicitHeight - 2
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
contentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
contentHeight + topPadding + bottomPadding)
margins: 6
verticalPadding: 8
horizontalPadding: 12
closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent | T.Popup.CloseOnReleaseOutsideParent
font{
family: "Microsoft YaHei"
pixelSize: 14
}
contentItem: Text {
text: control.text
font: control.font
color: "red"
}
background: Rectangle {
border.color: "red"
color: "white"
radius: 4
}
}
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window {
visible: true
width: 640
height: 480
title: qsTr("Qml EventLoop")
Rectangle{
width: 300
height: 300
border.color: "red"
anchors.centerIn: parent
Text{
text: "hover时显示自定义样式"
anchors.centerIn: parent
ToolTip.text: "自定义样式"
ToolTip.visible: mouse.containsMouse
ToolTip{
id: tip
text: "默认样式"
visible: !mouse.containsMouse
}
}
MouseArea{
id: mouse
anchors.fill: parent
hoverEnabled: true
}
}
}