QT C++在2D图形方面已经做的很完善了,在PC端(Windows、Linux和MaC)上都有很好的表现。

QT中的QML特别适合于移动端应用的开发,QML中的一些基本形状类型并不是一一地与Qt C++相对应,但是通过C++可以来扩展QML。

QQuickPaintedItem继承自QQuickItem,提供了使用QPainter API的方法来扩展QML中的2D图形项。

QQuickPaintedItem没有像QGraphicsItem那样提供shape()方法来获取图形项的具体实际形状,但是其包含contains()方法,我们可以间接地结合鼠标操作点来判断是否包含在实际形状范围内。

废话不多说,直接上测试代码:

CustomItem.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 
#ifndef CUSTOMITEM_H
#define CUSTOMITEM_H

#include <QQuickPaintedItem>
#include <QQuickItem>
#include <QMouseEvent>
#include <QPainter>

class CustomItem : public QQuickPaintedItem
{
    Q_OBJECT
    Q_PROPERTY(QString name READ name WRITE setName)
    Q_PROPERTY(QColor color READ color WRITE setColor)

public:
    CustomItem(QQuickItem *parent = nullptr);

QString name() const;
    void setName(const QString &name);

QColor color() const;
    void setColor(const QColor &color);

// override paint() for actual painting.
    virtual void paint(QPainter *painter);
    // override contans() for shape mask, Q_INVOKABLE for QML use.
    Q_INVOKABLE virtual bool contains(const QPointF &point) const;

virtual void mousePressEvent(QMouseEvent *event);
    virtual void mouseMoveEvent(QMouseEvent *event);
    virtual void mouseReleaseEvent(QMouseEvent *event);

private:
    QString m_name;
    QColor m_color;
};

#endif // CUSTOMITEM_H

 CustomItem.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
 
#include "CustomItem.h"
#include <QPainter>
#include <QPainterPathStroker>
#include <QDebug>

CustomItem::CustomItem(QQuickItem *parent)
    : QQuickPaintedItem(parent)
{
    setAcceptedMouseButtons(Qt::LeftButton
                            | Qt::RightButton
                            | Qt::MiddleButton);
    setFlag(QQuickItem::ItemHasContents);
}

QString CustomItem::name() const
{
    return m_name;
}

void CustomItem::setName(const QString &name)
{
    m_name = name;
}

QColor CustomItem::color() const
{
    return m_color;
}

void CustomItem::setColor(const QColor &color)
{
    m_color = color;
}

void CustomItem::paint(QPainter *painter)
{
    // pen & brush
);
    QLinearGradient gradient;
    gradient.setStart();
    gradient.setFinalStop();
    gradient.setColorAt(, Qt::blue);
    gradient.setColorAt(, Qt::green);
    gradient.setColorAt(, Qt::red);
    gradient.setColorAt(, Qt::yellow);
    gradient.setColorAt(, Qt::cyan);
    painter->setPen(pen);
    painter->setBrush(gradient);
    painter->setRenderHints(QPainter::Antialiasing, true);

// Unclosed shape
] =
    {
        QPointF(),
        QPointF(),
        QPointF(),
    };

painter->save();
    pen.setJoinStyle(Qt::MiterJoin);    // MiterJoin, BevelJoin, RoundJoin
    pen.setCapStyle(Qt::RoundCap);      // FlatCap, SquareCap, RoundCap
    pen.setStyle(Qt::DashLine);
    painter->drawPolyline(points, );
    painter->restore();

// Closed shape
    QPainterPath path;
    path.addEllipse(QRectF());
    painter->drawPath(path);

/* 三角形
    QPainterPath path;
    path.moveTo(width() / 2, 0);
    path.lineTo(width(), height());
    path.lineTo(0, height());
    path.lineTo(width() / 2, 0);
    painter->fillPath(path, m_color);
    */
}

bool CustomItem::contains(const QPointF &point) const
{
    // Unclosed shape
] =
    {
        QPointF(),
        QPointF(),
        QPointF(),
    };
    QPainterPath path;
    path.moveTo(points[]);
    path.lineTo(points[]);
    path.lineTo(points[]);
    QPainterPathStroker stroker;
    stroker.setWidth();
    stroker.setJoinStyle(Qt::MiterJoin);
    stroker.setCapStyle(Qt::RoundCap);
    stroker.setDashPattern(Qt::SolidLine);
    return stroker.createStroke(path).contains(point);

// Close shape
    QPainterPath path;
    path.addEllipse(QRectF());
    QPainterPathStroker stroker;
    stroker.setWidth();
    return path.contains(point) || stroker.createStroke(path).contains(point);

/* 三角形
    QPainterPath path;
    path.moveTo(width() / 2, 0);
    path.lineTo(width(), height());
    path.lineTo(0, height());
    path.lineTo(width() / 2, 0);
    QPainterPathStroker stroker;
    stroker.setWidth(10);
    return return path.contains(point) || stroker.createStroke(path).contains(point);
    */
}

void CustomItem::mousePressEvent(QMouseEvent *event)
{
    qDebug() << "CustomItem::mousePressEvent";
    QQuickPaintedItem::mousePressEvent(event);
}

void CustomItem::mouseMoveEvent(QMouseEvent *event)
{
    qDebug() << "CustomItem::mouseMoveEvent";
    QQuickPaintedItem::mouseMoveEvent(event);
}

void CustomItem::mouseReleaseEvent(QMouseEvent *event)
{
    qDebug() << "CustomItem::mouseReleaseEvent";
    QQuickPaintedItem::mouseReleaseEvent(event);
}

在main.cpp中注册CustomItem类型:qmlRegisterType<CustomItem>("CustomItem", 1, 0, "CustomItem");

 main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "CustomItem.h"

int main(int argc, char *argv[])
{
    qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));

QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

QGuiApplication app(argc, argv);

qmlRegisterType<CustomItem>(, "CustomItem");

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(-);
    }, Qt::QueuedConnection);
    engine.load(url);

return app.exec();
}

在qml文件中使用:

 main.qml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
 

Window {
    id: window
    visible: true
    width: 
    height: 
    title: qsTr("qml-2d-viewer")

Button {
        id: btn
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        text: "Populate"
        onClicked: {
            var object = Qt.createQmlObject(
                        'import QtQuick 2.12;
;
                         CustomItem {
                            width: 
                            height: 
                            x: window.width * Math.random()
                            y: window.height * Math.random()
                            name: "A simple Rectangle Item"
                            color: Qt.rgba(Math.random(), Math.random(), Math.random(), )

MouseArea {
                                anchors.fill: parent
                                onPressed: {
                                    if (parent.contains(Qt.point(mouse.x, mouse.y))){
                                        drag.target = parent
                                        parent.color = Qt.rgba(Math.random(), Math.random(), Math.random(), );
                                        parent.update();
                                    }
                                    else{
                                        drag.target = null
                                    }
                                }
                                drag.axis: Drag.XAndYAxis
                                drag.minimumX: 
                                drag.maximumX: window.width - parent.width
                                drag.minimumY: 
                                drag.maximumY: window.height - parent.width
                                }
                            }',
                        parent,
                        "dynamicSnippet");
        }
    }

// QML Rectangle Type
    Rectangle {
        id: blueSquare
        width: 
        x: window.width - width -     // making this item draggable, so don't use anchors
        color: "blue"
        visible: false

Text { text: ; color: "white"; anchors.centerIn: parent }

MouseArea {
            anchors.fill: parent
            //! [drag]
            drag.target: blueSquare
            drag.axis: Drag.XAndYAxis
            drag.minimumX: 
            drag.maximumX: window.width - parent.width
            drag.minimumY: 
            drag.maximumY: window.height - parent.width
            //! [drag]
        }
    }

// CustomItem Type Inherited from QQuickPaintedItem
    CustomItem {
        id: aRectangle
        width: 
        height: 
        name: "A simple Rectangle Item"
        color: "red"

MouseArea {
            anchors.fill: parent
            onPressed: {
                if (parent.contains(Qt.point(mouse.x, mouse.y))){
                    drag.target = parent
                    parent.color = Qt.rgba(Math.random(), Math.random(), Math.random(), );
                    parent.update();
                }
                else{
                    drag.target = null
                }
            }
            drag.axis: Drag.XAndYAxis
            drag.minimumX: 
            drag.maximumX: window.width - parent.width
            drag.minimumY: 
            drag.maximumY: window.height - parent.width
        }
    }
}

Q_INVOKABLE宏将contains()方法注册到元对象系统中,这样QML就可以调用该方法来判断鼠标指针点是否在图形项形状区域,从而实现精准拾取。

在QML中MouseArea为简单的鼠标交互提供了方便,比较容易使用,如果有了MouseArea,则C++中的鼠标响应事件就不再响应。

QQuickPaintedItem鼠标精准拾取(pick/select)研究的更多相关文章

  1. QGraphicsItem鼠标精准拾取(pick/select)研究

    在QT场景视图中,一个2D图形项是一个QGraphicsItem,我们可以通过继承来定义我们自己的图形项. 主要有以下三个虚函数需要重点关注: 1)   边界矩形(必须实现) virtual QRec ...

  2. Micro LED巨量转移技术研究进展

    近年来,Micro LED因其功耗低.响应快.寿命长.光效率高等特点,被视为继LCD.OLED之后的新一代显示面板技术.Micro LED的英文全名是Micro Light Emitting Diod ...

  3. OpenGL中的拾取模式( Picking)

    1. Opengl中的渲染模式有三种:(1)渲染模式,默认的模式:(2)选择模式, (3)反馈模式.如下 GLint glRenderMode(GLenum mode) mode可以选取以下三种模式之 ...

  4. Selenium:利用select模块处理下拉框

    在利用selenium进行UI自动化测试过程中,经常会遇到下拉框选项,这篇博客,就介绍下如何利用selenium的Select模块来对标准select下拉框进行操作... 首先导入Select模块: ...

  5. js实现鼠标拖动框选元素小狗

    方法一: <html> <head></head> <style> body{padding:100px;} .fileDiv{float:left;w ...

  6. WebGL射线拾取模型——八叉树优化

    经过前面2篇WebGL射线拾取模型的文章,相信大家对射线和模型面片相交的原理已经有所了解,那么今天我们再深入探究关于射线拾取的一个问题,那就是遍历场景中的所有与射线相交的模型的优化问题.首先我们来复习 ...

  7. 微软的鼠标 Microsoft mouse

    微软是做软件出身的厂商, 所以微软开发的软件质量毋庸置疑,Windows操作系统还有诸如Office的办公软件拥有庞大的用户群. 微软家的Visual Studio也被号称宇宙最强IDE,我个人也每天 ...

  8. Selenium: 利用select模块操作下拉框

    在利用selenium进行UI自动化测试过程中,经常会遇到下拉框选项,这篇博客,就介绍下如何利用selenium的Select模块来对标准select下拉框进行操作... 首先导入Select模块: ...

  9. 转:SDL2源代码分析

    1:初始化(SDL_Init()) SDL简介 有关SDL的简介在<最简单的视音频播放示例7:SDL2播放RGB/YUV>以及<最简单的视音频播放示例9:SDL2播放PCM>中 ...

随机推荐

  1. V4l2初识(七)-----------浅析app获取虚拟摄像头数据的过程

    继续分析数据的获取过程: 1.请求分配的缓冲区: ioctl(4,VIDIOC_REQBUFS) vidioc_reqbufs 2.查询和映射缓冲区   ioctl(4,VIDIOC_QUERYBUF ...

  2. MyBatis学习笔记-1 Idea配置MyBatis

    一.创建工程 1.创建Java项目,勾选Java EE,Next,修改名称,Finish 2.在WEB-INF下创建两个文件夹classes和lib,分别用作输出文件目录和库文件目录 3.File-P ...

  3. pikachu SQL-Injection

    1.数字型注入(POST) 可以看到,这个参数提交是POST类型的,用burp. 测试参数id id='&submit=%E6%9F%A5%E8%AF%A2 可以看到有报错回显,而且根据回显可 ...

  4. MySQL拓展 视图,触发器,事务,存储过程,内置函数,流程控制,索引,慢查询优化,数据库三大设计范式

    视图: 1.什么是视图 视图就是通过查询得到一张虚拟表,然后保存下来,下次直接使用即可 2.为什么要用视图 如果要频繁使用一张虚拟表,可以不用重复查询 3.如何使用视图 create view tea ...

  5. Python进阶-VII 内置函数

    一.内置函数引入 我们已经了解的有; print()  input() range() next()  dir() str() int() list() set() tuple() dict() he ...

  6. BBS 03day

    目录 BBS_03 day: 自定义标签 过滤器: 文章的点赞,点彩功能: 文章的评论功能 transaction用法: 自定义 标签代码展示: BBS_03 day: 自定义标签 过滤器: --&g ...

  7. [LeetCode] 925. Long Pressed Name 长按键入的名字

    Your friend is typing his name into a keyboard.  Sometimes, when typing a character c, the key might ...

  8. 《TP5.0学习笔记---模板变量输出、替换和赋值篇》

    原文地址:http://blog.csdn.net/self_realian/article/details/75214922 模板变量输出.替换和赋值 我们看一下文件编译的结果,我们知道我们现在写的 ...

  9. 解决Spring Cloud中Feign第一次请求失败的问题

    在Spring Cloud中,Feign和Ribbon在整合了Hystrix后,可能会出现首次调用失败的问题 com.netflix.hystrix.exception.HystrixTimeoutE ...

  10. asp.net core 3.0 身份认证 替换为自已的提供程序 AuthenticationStateProvider replace to SelfAuthenticationStateProvider

    public void ConfigureServices(IServiceCollection services) { // 添加身份验证服务 services.AddAuthorizationCo ...