【写在前面】

在 Qt 的 Quick 模块中,QQuickPaintedItem 是一个非常有用的类,它允许我们在 Qml 中自定义绘制逻辑。

我们可以通过这种方式实现水印工具,包括在文本、图片或整个窗口上添加水印。

本文将介绍如何在 Qml 中实现一个简单但功能强大的水印工具,包括水印文本的透明度、颜色、字体大小、旋转角度等自定义功能。


【正文开始】

一、效果图

二、水印工具类的设计

首先,我们需要设计一个 C++ 类来表示水印工具。这个类将继承自 QQuickPaintedItem,并添加一些属性来控制水印的外观和行为。这些属性包括水印文本、图像、大小、间距、偏移量、旋转角度、字体和字体颜色。

watermark.h

Watermark 类的头文件中,我们声明了所有的属性和相应的信号、槽函数。使用 Q_PROPERTY 宏来声明 Qml 中可访问的属性。

#ifndef WATERMARK_H
#define WATERMARK_H #include <QQuickPaintedItem> QT_FORWARD_DECLARE_CLASS(WatermarkPrivate); class Watermark : public QQuickPaintedItem
{
Q_OBJECT // 声明QML中可访问的属性
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged FINAL)
Q_PROPERTY(QUrl image READ image WRITE setImage NOTIFY imageChanged FINAL)
Q_PROPERTY(QSize markSize READ markSize WRITE setMarkSize NOTIFY markSizeChanged FINAL)
Q_PROPERTY(QPointF gap READ gap WRITE setGap NOTIFY gapChanged FINAL)
Q_PROPERTY(QPointF offset READ offset WRITE setOffset NOTIFY offsetChanged FINAL)
Q_PROPERTY(qreal rotate READ rotate WRITE setRotate NOTIFY rotateChanged FINAL)
Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged FINAL)
Q_PROPERTY(QColor fontColor READ fontColor WRITE setFontColor NOTIFY fontColorChanged FINAL) public:
Watermark(QQuickItem *parent = nullptr);
~Watermark(); // 属性的getter和setter函数
QString text() const;
void setText(const QString &text); QUrl image() const;
void setImage(const QUrl &image); QSize markSize() const;
void setMarkSize(const QSize &markSize); QPointF gap() const;
void setGap(const QPointF &gap); QPointF offset() const;
void setOffset(const QPointF &offset); qreal rotate() const;
void setRotate(qreal rotate); QFont font() const;
void setFont(const QFont &font); QColor fontColor() const;
void setFontColor(const QColor &fontColor); signals:
void textChanged();
void imageChanged();
void markSizeChanged();
void gapChanged();
void offsetChanged();
void rotateChanged();
void fontChanged();
void fontColorChanged(); protected:
void paint(QPainter *painter); private:
Q_DECLARE_PRIVATE(Watermark);
QScopedPointer<WatermarkPrivate> d_ptr;
}; #endif // WATERMARK_H

watermark.cpp

Watermark 类的实现文件中,我们主要实现了属性的 settergetter 函数,这些函数在属性值改变时会触发相应的信号,并调用update()函数来请求重新绘制。同时,我们也实现了paint()函数,它使用 QPainter 来绘制水印。

// watermark.cpp的实现省略,具体可参考提供的 watermark.cpp 文件

WatermarkPrivate.h

WatermarkPrivateWatermark 类的私有实现部分,它包含了所有的成员变量和辅助函数。这些成员变量包括水印文本、图像URL、网络请求回复、图像缓存、字体和字体颜色等。

// WatermarkPrivate类的声明省略,具体可参考watermark.cpp文件中的WatermarkPrivate部分

三、 Qml 中的使用

main.qml

在 Qml 文件中,我们可以使用 Watermark 元素来添加水印。通过设置 Watermark 的属性,我们可以控制水印的外观和行为。

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.15
import QtQuick.Layouts 1.15 import DelegateUI.Controls 1.0 Window {
id: window
width: 1080
height: 600
visible: true
title: qsTr("DelegateUI Watermark") RowLayout {
anchors.fill: parent ColumnLayout {
Layout.preferredWidth: parent.width * 0.5
Layout.preferredHeight: parent.height * 0.5 Item {
id: content1
Layout.fillWidth: true
Layout.fillHeight: true Watermark {
id: watermark1
anchors.fill: parent
offset.x: -50
offset.y: -50
rotate: slider1.value
fontColor: "#30ff0000"
} Text {
anchors.centerIn: parent
text: qsTr("文字水印测试")
font.pointSize: 36
}
} RowLayout {
Layout.fillWidth: true
Layout.maximumHeight: 40 Slider {
id: slider1
Layout.preferredWidth: 150
Layout.fillHeight: true
value: -22
from: -360
to: 360
stepSize: 1
} TextField {
id: markText
Layout.fillWidth: true
Layout.fillHeight: true
text: "DelegateUI Watermark"
placeholderText: qsTr("输入水印文本")
font.family: "微软雅黑"
selectByMouse: true
} Button {
Layout.preferredWidth: 80
Layout.fillHeight: true
text: qsTr("确定")
onClicked: watermark1.text = markText.text;
} Button {
Layout.preferredWidth: 80
Layout.fillHeight: true
text: qsTr("导出")
onClicked: {
content1.grabToImage((result)=>{
result.saveToFile("./content1.png");
Qt.openUrlExternally("file:./");
});
}
}
}
} ColumnLayout {
Layout.preferredWidth: parent.width * 0.5
Layout.preferredHeight: parent.height * 0.5 Item {
id: content2
Layout.fillWidth: true
Layout.fillHeight: true Watermark {
id: watermark2
anchors.fill: parent
offset.x: -50
offset.y: -50
markSize.width: 200
markSize.height: 150
rotate: slider2.value
opacity: 0.2
} Text {
anchors.centerIn: parent
text: qsTr("图像水印测试")
font.pointSize: 36
}
} RowLayout {
Layout.fillWidth: true
Layout.maximumHeight: 40 Slider {
id: slider2
Layout.preferredWidth: 150
Layout.fillHeight: true
value: -22
from: -360
to: 360
stepSize: 1
} TextField {
id: markImage
Layout.fillWidth: true
Layout.fillHeight: true
text: "https://avatars.githubusercontent.com/u/33405710?v=4"
placeholderText: qsTr("输入水印图片链接")
font.family: "微软雅黑"
selectByMouse: true
} Button {
Layout.preferredWidth: 80
Layout.fillHeight: true
text: qsTr("确定")
onClicked: watermark2.image = markImage.text;
} Button {
Layout.preferredWidth: 80
Layout.fillHeight: true
text: qsTr("导出")
onClicked: {
content2.grabToImage((result)=>{
result.saveToFile("./content2.png");
Qt.openUrlExternally("file:./");
});
}
}
}
}
}
}

在这个 Qml 文件中,我们创建了两个个 Watermark 元素并通过设置 Watermark 的各种属性,我们实现了一个带有文本和图像的水印效果,并且可以控制水印的大小、间距、偏移量、旋转角度、字体和字体颜色。


【结语】

通过使用 QQuickPaintedItem,我们可以在 Qml 中实现了一个功能丰富的水印工具。

这个工具允许我们自定义水印的外观和行为,并且可以很方便地在 Qml 中使用。

最后:项目链接(多多star呀.._):

Github: https://github.com/mengps/QmlControls

Gitee: https://gitee.com/MenPenS/QmlControls

Qml 中实现水印工具的更多相关文章

  1. qml 中 使用 shader

    使用绘制工具如Photoshop .Flash已经可以创建许多效果非常绚丽的图像.动画等. Qt/QML 的努力其实是在这些工具发展的后面, 因此很多效果在Qt中无法实现. 不得不佩服Qt小组的才智, ...

  2. R语言作为BI中ETL的工具

    R语言作为BI中ETL的工具,增删改 R语言提供了强大的R_package与各种数据库进行数据交互. 外加其强大数据变换清洗函数,为ETL提供一条方便快捷的道路. RODBC ROracal RMys ...

  3. iOS开发小技巧--微博项目中的键盘工具条

    微博项目中的键盘工具条 项目中的键盘工具条不能使用inputAccessoryView,因为inputAccessoryView不能实现键盘隐藏的时候,工具条还显示在眼前,如图: 所以,果断决定将工具 ...

  4. qml中打开本地html

    main.cpp QString tmploc = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); QDi ...

  5. MAPINFO中利用GridMaker工具创建栅格图层

    在工作中需要使用栅格地图,以往都是由研发人员来创建,今天偶然发现Mapinfo中有GridMaker这样一个工具,结合网络搜索自己试了一下,居然做成功了,这里把步骤记录下来,方便以后查看. 1.首先在 ...

  6. java中常用的工具类(一)

    我们java程序员在开发项目的是常常会用到一些工具类.今天我汇总了一下java中常用的工具方法.大家可以在项目中使用.可以收藏!加入IT江湖官方群:383126909 我们一起成长 一.String工 ...

  7. Engine中执行gp工具返回的要素图层如何获取?

    来自:http://zhihu.esrichina.com.cn/?/question/12087 Engine中执行gp工具返回的[解决办法]:需要用gpUtils.DecodeFeatureLay ...

  8. 在 virtualbox 的 centos7 虚拟机中安装增强工具

    在 virtualbox 的 centos7 虚拟机中安装增强工具 centos7 刚刚安装完成时,直接安装 virtualbox 增强工具会出错,需要先把 gcc / kernel-devel / ...

  9. JAVA中封装JSONUtils工具类及使用

    在JAVA中用json-lib-2.3-jdk15.jar包中提供了JSONObject和JSONArray基类,用于JSON的序列化和反序列化的操作.但是我们更习惯将其进一步封装,达到更好的重用. ...

  10. 在VS2103环境中集成Doxygen工具

    自己已将学习了两三次了吧,差不多这次该总结一下: Doxygen是一种开源跨平台的,以类似JavaDoc风格描述的文档系统,完全支持C.C++.Java.Objective-C和IDL语言,部分支持P ...

随机推荐

  1. KubeSphere 集群配置 NFS 存储解决方案

    作者:申红磊,QingCloud 容器解决方案架构师,开源项目爱好者,KubeSphere Member 在正式阅读本文之前,先友情提醒一下:不建议您在生产环境中使用 NFS 存储(特别是 Kuber ...

  2. 买游戏本玩战锤40K ?ToDesk云电脑教你2元升级旧电脑,省钱!

    <战锤40K:星际战士>终于出续作了!不得不说这款多人射击游戏的热度实在太高啦,刚发布两天就登顶Steam销量第一名. <战锤40K:星际战士2>不仅继承了前作的精髓,更在画面 ...

  3. [Windows]文件搜索利器Everything(附zip)

    前言 写代码过程中,老大突然发一条信息 老大:这周周报发一下. 我:好的. 然后我就 显示桌面 打开-我的电脑 找到E盘,找到周报文件夹 寻找到所有周报中今天的周报 复制发送 当我用上Everythi ...

  4. Python一些常见的技巧及语句!!

    题记:关于遇到的一些python代码或者不清楚用法的函数.类别等我会在这里记录下来,方便日后学习和交流.之后研究生三年我会持续更新学习,可能得记录几千个吧. 1. copy.copy()和copy.d ...

  5. 介绍 GGUF-my-LoRA

    随着 llama.cpp 对 LoRA 支持的重构,现在可以将任意 PEFT LoRA 适配器转换为 GGUF,并与 GGUF 基础模型一起加载运行. 为简化流程,我们新增了一个名为 GGUF-my- ...

  6. ScheduledThreadPoolExecutor与System#nanoTime

    一直流传着Timer使用的是绝对时间,ScheduledThreadPoolExecutor使用的是相对时间,那么ScheduledThreadPoolExecutor是如何实现相对时间的? 先看看S ...

  7. 成为JavaGC专家Part I — 深入浅出Java垃圾回收机制

    对于Java开发人员来说,了解垃圾回收机制(GC)有哪些好处呢?首先可以满足作为一名软件工程师的求知欲,其次,深入了解GC如何工作可以帮你写出更好的Java应用. 这仅仅代表我个人的意见,但我坚信一个 ...

  8. 探究内存泄露—Part1—编写泄露代码

    本文由 ImportNew - 黄索远 翻译自 captaindebug.如需转载本文,请先参见文章末尾处的转载要求. ImportNew注:如果你也对Java技术翻译分享感兴趣,欢迎加入我们的 Ja ...

  9. rabbitmq-c与amqp扩展安装

    最近需要使用RabbitMQ进行消息队列处理 1.安装rabbitmq-c 在安装amqp之前需要先安装rabbitmq-c扩展 rabbitmq-c下载网址:https://github.com/a ...

  10. 终于解决了.net在线客服系统总是被360误报的问题(对软件进行数字签名)

    升讯威在线客服与营销系统是基于 .net core / WPF 开发的一款在线客服软件,宗旨是: 开放.开源.共享.努力打造 .net 社区的一款优秀开源产品. 背景 我在业余时间开发的这个客服系统, ...