自定义QGraphcsItem旋转移动缩放组合

news2025/1/12 21:47:12

简单的记录下学习自定义QGraphicsItem 移动、旋转、缩放、组合。

1. QGraphicsView缩放

通过鼠标滚轮缩放整个视图
重写GraphicsView的wheelEvent(QWheelEvent *event)事件

在这里插入图片描述

//
//QttGraphicsView::QttGraphicsView(QGraphicsScene* scene, QWidget* parent) : QGraphicsView(scene, parent){}
void QttGraphicsView::wheelEvent(QWheelEvent *event)
{
    static float scale = 1.1;

    auto angle = event->angleDelta();

    if(angle.y() > 0)
    {
        this->scale(scale, scale);
    }
    else
    {
        this->scale(1/scale, 1/scale);
    }
}

2.拖动、旋转、缩放

继承重写QGraphicsItem

#ifndef QTTGRAPHICSITEMA_H
#define QTTGRAPHICSITEMA_H

#include <QObject>
#include <QGraphicsItem>
#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QPixmap>
#include <QRectF>
#include <QVector3D>

//enum MyCursorTypes{
//    Normal      = 0,
//    Move        = 1,
//    Rotate      = 2,
//    LeftTop     = 3,
//    LeftBottom  = 4,
//    RightTop    = 5,
//    RightBottom = 6,
//};

class QttGraphicsItemCursor;

class QttGraphicsItemA : public QObject, public QGraphicsItem
{
    Q_OBJECT
    Q_INTERFACES(QGraphicsItem)
public:

    QttGraphicsItemA(double x, double y, double width, double height);

    QRectF getRect() const;

protected:
    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
    virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
    virtual QRectF boundingRect() const override;
    void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override;


private:
    void rotate(QGraphicsSceneMouseEvent * event);

private:
    // 主框大小,即四边形虚线范围
    QRectF m_rect;
    qreal m_width, m_height;
    qreal m_left, m_top, m_right, m_bottom;
    qreal m_scale;
    QSize minSize;


    QRectF m_leftTopRect, m_rightTopRect, m_rightBottomRect, m_leftBottomRect;

    qreal m_line_rotate = 20;

    QPixmap m_leftTopPix;
    QPixmap m_rightTopPix;
    QPixmap right_BottomPix;
    QPixmap m_leftBottomPix;
    QPixmap m_rotatePix;
    QttGraphicsItemCursor* item_rotate;
    QttGraphicsItemCursor* item_leftTop;
    QttGraphicsItemCursor* item_rightTop;
    QttGraphicsItemCursor* item_rightBottom;
    QttGraphicsItemCursor* item_leftBottom;

    QPointF pPress;

    void init_painter_button();
    //!
    void paint_button(qreal radius);
};

//! 缩放、旋转图标item
//! 用于判断鼠标是否放再特定位置
class QttGraphicsItemCursor : public QObject, public QGraphicsItem
{
    Q_OBJECT
    Q_INTERFACES(QGraphicsItem)
public:
    QttGraphicsItemCursor(double x, double y, double width, double height, Qt::CursorShape type = Qt::ArrowCursor);
    void setItemRect(QRectF rect);
    void setCursorType(Qt::CursorShape type);
    Qt::CursorShape getCursorShape(){return m_cursor_shape;}

    bool isPress();

protected:
    virtual QRectF boundingRect() const override;
    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
    virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
    void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override;
    void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
    void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;


private:
    QRectF m_rect;
    Qt::CursorShape m_cursor_shape;
};

#endif // QTTGRAPHICSITEMA_H
#include "qttgraphicsitema.h"
#include <QPainter>
#include <QDebug>
#include <QStyleOptionGraphicsItem>
#include <QDebug>
#include <QImage>
#include <QPolygonF>
#include <QVector2D>
#include <QVector3D>
#include <QtMath>
#include <cmath>

QRectF ImageRect2(QRectF rect)
{
    //图片占主题轮廓的比例0.8
    double x = rect.x();
    double y = rect.y();
    double width = rect.width();
    double height = rect.height();

    double new_x = x+width*0.1;
    double new_y = y+height*0.1;
    double new_w = width*0.8;
    double new_h = height*0.8;

    return QRectF(new_x, new_y, new_w, new_h);
}

double getMargin(QRectF rect)
{
    return rect.width()*0.1 <= rect.height()*0.1 ? rect.width()*0.1 : rect.height()*0.1;
}

QttGraphicsItemA::QttGraphicsItemA(double x, double y, double width, double height) : m_rect(x, y, width, height)
    , m_width(width)
    , m_height(height)
    , m_left(x)
    , m_top(y)
    , m_right(x+width)
    , m_bottom(y+height)
    , m_scale(width/height)
    , minSize(40, 40*m_scale)
{
    this->setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsFocusable);

    this->setAcceptHoverEvents(true);

    m_leftTopPix = QPixmap(":/circle_grey.png");
    m_rightTopPix = QPixmap(":/circle_grey.png");
    right_BottomPix = QPixmap(":/circle_grey.png");
    m_leftBottomPix = QPixmap(":/circle_grey.png");
    m_rotatePix = QPixmap(":/rotate_hover.png");

    item_rotate = nullptr;
    item_leftTop = nullptr;
    item_rightTop = nullptr;
    item_rightBottom = nullptr;
    item_leftBottom = nullptr;

    init_painter_button();
}

void QttGraphicsItemA::init_painter_button()
{
    double radius = getMargin(m_rect)/2;
    if(item_leftBottom == nullptr)
    {
        item_leftBottom = new QttGraphicsItemCursor(m_rect.x()-radius, m_rect.y()+m_rect.height()-radius, radius*2, radius*2, Qt::SizeBDiagCursor);
        item_leftBottom->setCursorType(Qt::CursorShape::SizeBDiagCursor);
        item_leftBottom->setParentItem(this);
        item_leftBottom->setVisible(false);
    }

    if(item_leftTop == nullptr)
    {
        item_leftTop = new QttGraphicsItemCursor(m_rect.x()-radius, m_rect.y()-radius, radius*2, radius*2, Qt::SizeFDiagCursor);
        item_leftTop->setCursorType(Qt::CursorShape::SizeFDiagCursor);
        item_leftTop->setParentItem(this);
        item_leftTop->setVisible(false);
    }

    if(item_rightBottom == nullptr)
    {
        item_rightBottom = new QttGraphicsItemCursor(m_rect.x()+m_rect.width()-radius, m_rect.y()+m_rect.height()-radius, radius*2, radius*2, Qt::CursorShape::SizeFDiagCursor);
        item_rightBottom->setCursorType(Qt::CursorShape::SizeFDiagCursor);
        item_rightBottom->setParentItem(this);
        item_rightBottom->setVisible(false);
    }

    if(item_rightTop == nullptr)
    {
        item_rightTop = new QttGraphicsItemCursor(m_rect.x()+m_rect.width()-radius, m_rect.y()-radius, radius*2, radius*2, Qt::SizeBDiagCursor);
        item_rightTop->setCursorType(Qt::CursorShape::SizeBDiagCursor);
        item_rightTop->setParentItem(this);
        item_rightTop->setVisible(false);
    }

    if(item_rotate == nullptr)
    {
        item_rotate = new QttGraphicsItemCursor(m_rect.x()+m_rect.width()/2-radius, m_rect.y()-m_line_rotate-radius*2, radius*2, radius*2, Qt::SizeAllCursor);
        item_rotate->setCursorType(Qt::CursorShape::SizeAllCursor);
        item_rotate->setParentItem(this);
        item_rotate->setVisible(false);
    }
}

void QttGraphicsItemA::paint_button(qreal radius)
{
    if(item_leftBottom)
    {
        item_leftBottom->setItemRect(QRectF(m_rect.x()-radius, m_rect.y()+m_rect.height()-radius, radius*2, radius*2));
        item_leftBottom->setVisible(true);
    }

    if(item_leftTop)
    {
        item_leftTop->setItemRect(QRectF(m_rect.x()-radius, m_rect.y()-radius, radius*2, radius*2));
        item_leftTop->setVisible(true);
    }

    if(item_rightTop)
    {
        item_rightBottom->setItemRect(QRectF(m_rect.x()+m_rect.width()-radius, m_rect.y()+m_rect.height()-radius, radius*2, radius*2));
        item_rightBottom->setVisible(true);
    }

    if(item_leftBottom)
    {
        item_rightTop->setItemRect(QRectF(m_rect.x()+m_rect.width()-radius, m_rect.y()-radius, radius*2, radius*2));
        item_rightTop->setVisible(true);
    }

    if(item_rotate)
    {
        item_rotate->setItemRect(QRectF(m_rect.x()+m_rect.width()/2-radius, m_rect.y()-m_line_rotate-radius*2, radius*2, radius*2));
        item_rotate->setVisible(true);
    }
}

void QttGraphicsItemA::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/)
{
    QPixmap pix(":/timg.jpg");
    painter->drawPixmap(ImageRect2(m_rect), pix, pix.rect());

    if(isSelected())
    {
        // 图像轮廓
        QPen pen;
        pen.setStyle(Qt::DashLine);
        pen.setColor(QColor(0,0,255));
        painter->setPen(pen);
        painter->drawRect(m_rect);

        // 5个顶点item
        double radius = getMargin(m_rect)/2;
        paint_button(radius);

        //line
        m_line_rotate = radius*2;
        QPointF start(m_rect.x()+m_rect.width()/2, m_rect.y());
        QPointF end(m_rect.x()+m_rect.width()/2, m_rect.y()-m_line_rotate);
        painter->drawLine(QLineF(start, end));
    }
    else
    {
        if(item_rotate)item_rotate->setVisible(false);
        if(item_leftTop)item_leftTop->setVisible(false);
        if(item_rightTop)item_rightTop->setVisible(false);
        if(item_leftBottom)item_leftBottom->setVisible(false);
        if(item_rightBottom)item_rightBottom->setVisible(false);
    }
}

void QttGraphicsItemA::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    if(flags() & ItemIsMovable)
    {
        if ((event->buttons() & Qt::LeftButton))
        {
            QPointF diff = event->pos()-event->lastPos();

            qreal dx = diff.x();
            qreal dy = diff.y();

            QRectF rect = m_rect;


            if(item_rotate->isPress())
            {
                rotate(event);
            }
            else if(item_leftBottom->isPress())
            {
                dx = (rect.width()-dx*2 < minSize.width()) ? (rect.width()-minSize.width())/2 : dx;
                dy = (rect.height()+dy*2 < minSize.height()) ? (minSize.height()- rect.height())/2 : dy;
                rect.adjust(dx, -dy, -dx, dy);
            }
            else if(item_leftTop->isPress())
            {
                dx = (rect.width()-dx*2 < minSize.width()) ? (rect.width()-minSize.width())/2 : dx;
                dy = (rect.height()-dy*2 < minSize.height()) ? (rect.height()-minSize.height())/2 : dy;
                rect.adjust(dx, dy, -dx, -dy);
            }
            else if(item_rightBottom->isPress())
            {
                dx = (rect.width()+dx*2 < minSize.width()) ? (minSize.width()-rect.width())/2 : dx;
                dy = (rect.height()+dy*2 < minSize.height()) ? (minSize.height()- rect.height())/2 : dy;
                rect.adjust(-dx, -dy, dx, dy);
            }
            else if(item_rightTop->isPress())
            {
                dx = (rect.width()+dx*2 < minSize.width()) ? (minSize.width()-rect.width())/2 : dx;
                dy = (rect.height()-dy*2 < minSize.height()) ? (rect.height()-minSize.height())/2 : dy;
                rect.adjust(-dx, dy, dx, -dy);
            }
            else if(getRect().contains(event->pos()))
            {
                //! 此方法在旋转item后移动会抖动,具体原因不了解
                //QPointF diff = event->scenePos() - this->pPress;
                //this->setPos(diff);
                //! 通过计算鼠标在scene中前后两次位置差,移动item
                QPointF diff = event->scenePos() - event->lastScenePos();
                // 不用鼠标在item中坐标是因为当item旋转后计算所得的值不可直接使用
                //QPointF diff2 = event->pos() - event->lastPos();
                this->moveBy(diff.x(),diff.y());
            }

            if(m_rect != rect)
            {
                prepareGeometryChange();
                m_rect = rect;
            }
            this->update();
            this->scene()->update();
        }
    }

    //此处不调用, 影响功能
    //QGraphicsItem::mouseMoveEvent(event);
}

void QttGraphicsItemA::rotate(QGraphicsSceneMouseEvent *event)
{
    QPointF originPos = this->getRect().center();
    // 从原点延伸出去两条线,鼠标按下时的点和当前鼠标位置所在点的连线
    QLineF p1 = QLineF(originPos, pPress);
    QLineF p2 = QLineF(originPos, event->pos());
    // 旋转角度
    qreal dRotateAngle = p2.angleTo(p1);

    // 设置旋转中心
    this->setTransformOriginPoint(originPos);

    // 计算当前旋转的角度
    qreal dCurAngle = this->rotation() + dRotateAngle;
    while (dCurAngle > 360.0) {
        dCurAngle -= 360.0;
    }

    prepareGeometryChange();
    // 设置旋转角度
    this->setRotation(dCurAngle);
}

void QttGraphicsItemA::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    pPress = event->pos();

    QGraphicsItem::mousePressEvent(event);
}

void QttGraphicsItemA::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsItem::mouseReleaseEvent(event);
}


QRectF QttGraphicsItemA::getRect() const
{
    QRectF rect = m_rect;
    if(isSelected() || !isSelected())
    {
        qreal radius = getMargin(rect)/2;
        rect.adjust(-radius, -radius, radius, radius);
        rect.adjust(0, -m_line_rotate-radius, 0, 0);
    }
    return rect;
}

QRectF QttGraphicsItemA::boundingRect() const
{
    QRectF rect = getRect();
    return rect;
}


void QttGraphicsItemA::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
    if(m_rect.contains(event->pos())) setCursor(Qt::OpenHandCursor);

    QGraphicsItem::hoverMoveEvent(event);
}





//!####################################################################################################################################
//!
//!
//!
//!####################################################################################################################################
//! QttGraphicsItemCursor
//!
QttGraphicsItemCursor::QttGraphicsItemCursor(double x, double y, double width, double height, Qt::CursorShape type) : m_rect(x, y, width, height)
    , m_cursor_shape(type)
{
    this->setAcceptHoverEvents(true);
}

void QttGraphicsItemCursor::setItemRect(QRectF rect)
{
    if(rect != m_rect)
    {
        prepareGeometryChange();
        m_rect = rect;
    }
}

void QttGraphicsItemCursor::setCursorType(Qt::CursorShape type)
{
    m_cursor_shape = type;
}

QRectF QttGraphicsItemCursor::boundingRect() const
{
    return m_rect;
}

void QttGraphicsItemCursor::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
    switch (m_cursor_shape) {
    case Qt::CursorShape::ArrowCursor:
    {
        QPixmap pix(":/circle_grey.png");
        painter->drawPixmap(/*ImageRect2(m_rect)*/m_rect, pix, pix.rect());
    }break;
    case Qt::CursorShape::OpenHandCursor:
    {
        QPixmap pix(":/circle_grey.png");
        painter->drawPixmap(/*ImageRect2(m_rect)*/m_rect, pix, pix.rect());

    }break;
    case Qt::CursorShape::SizeAllCursor:
    {
        QPixmap pix(":/rotate_hover.png");
        painter->drawPixmap(/*ImageRect2(m_rect)*/m_rect, pix, pix.rect());

    }break;
    case Qt::CursorShape::SizeFDiagCursor:
    {
        QPixmap pix(":/circle_grey.png");
        painter->drawPixmap(/*ImageRect2(m_rect)*/m_rect, pix, pix.rect());

    }break;
    case Qt::CursorShape::SizeBDiagCursor:
    {
        QPixmap pix(":/circle_grey.png");
        painter->drawPixmap(/*ImageRect2(m_rect)*/m_rect, pix, pix.rect());

    }break;
    default:
        break;
    }
}

void QttGraphicsItemCursor::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
    QPointF pos = event->pos();
    if(!m_rect.contains(pos))
    {
        setCursor(Qt::ArrowCursor);
    }
    else
    {
        setCursor(m_cursor_shape);
    }

    QGraphicsItem::hoverMoveEvent(event);
}

void QttGraphicsItemCursor::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsItem::mouseMoveEvent(event);
}

void QttGraphicsItemCursor::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsItem::mousePressEvent(event);
}

void QttGraphicsItemCursor::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsItem::mouseReleaseEvent(event);
}

void QttGraphicsItemCursor::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
    setCursor(Qt::ArrowCursor);
    QGraphicsItem::hoverEnterEvent(event);
}
void QttGraphicsItemCursor::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
    setCursor(Qt::ArrowCursor);
    QGraphicsItem::hoverLeaveEvent(event);
}

//! 判断设定的鼠标图标样式是否与实际样式一致,是则返回true,否则返回false
bool QttGraphicsItemCursor::isPress()
{
    return this->cursor() == m_cursor_shape;
}

3. 使用

m_scene = new QttGraphicsScene();

// ui->graphicsView 是在ui界面添加的QGraphicsView,然后提升为QttGraphicsView
ui->graphicsView->setScene(scene);

QttGraphicsItemA* item = new QttGraphicsItemA(0,0,200,200);

m_scene->addItem(item);

4.组合

//组合
void Widget::on_pushButton_clicked()
{
    auto items = m_scene->selectedItems();
	if(items.length() <= 0) return;
    QGraphicsItemGroup *itemGroup = new QGraphicsItemGroup;
    itemGroup->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
    scene->addItem(itemGroup);

    foreach (auto item, items) {
        itemGroup->addToGroup(item);
    }
}

//取消组合
void Widget::on_pushButton_2_clicked()
{
    auto items = m_scene->selectedItems();
    if(items.length() != 1) return;
    QGraphicsItemGroup *itemGroup = reinterpret_cast<QGraphicsItemGroup *>(items.at(0));
    itemGroup->removeFromGroup(itemGroup->childItems().first());
    m_scene->destroyItemGroup(itemGroup);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/917402.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

经营决策垂直大模型——WinPlan经营大脑9月正式上线

经营决策产品提供商「数利得科技」(以下简称“数利得”)日前获近千万天使轮融资,由耀途资本独家投资。本轮融资资金将用于产品研发和算法模型搭建。 数利得成立于2022年,核心成员出身于阿里旗下钉钉,曾负责财税、业财一体、生态开放等业务,商业化经验丰富。在与众多企业…

如何快速查询京东快递并查询超时状态?

随着电子商务的蓬勃发展&#xff0c;快递成为了我们日常生活中不可或缺的一部分。而在众多快递公司中&#xff0c;京东快递以其高效、可靠的服务赢得了广大用户的青睐。然而&#xff0c;查询京东快递并同时查询快递的超时状态却一直是用户们头痛的问题。今天&#xff0c;我将为…

什么是Nginx HA?

什么是Nginx HA 1.1 什么是Nginx HA?1.2 高可用性的类型1.3 理解Nginx HA 示例1.4为什么高可用性很重要&#xff1f;1.5 高可用是如何实现的&#xff1f;1.6 如何支持高可用性?1.7 最佳实践&#xff1a;高可用性 1.1 什么是Nginx HA? 高可用性(HA) 是指系统通常通过使用内置…

水体测试积分球

水质分析包括观察分析、嗅味分析、仪器分析和化验分析等方法。排除分析过程中的影响因素&#xff0c;确保得到数据的准确性&#xff0c;保证分析质量&#xff0c;让人们深入了解水情况&#xff0c;合理利用水资源。在水质分析化验中&#xff0c;要对样品进行严格的控制&#xf…

DNDC模型---土壤碳储量、温室气体排放、农田减排、土地变化、气候变化中的应用

由于全球变暖、大气中温室气体浓度逐年增加等问题的出现&#xff0c;“双碳”行动特别是碳中和已经在世界范围形成广泛影响。国家领导人在多次重要会议上讲到&#xff0c;要把“双碳”纳入经济社会发展和生态文明建设整体布局。同时&#xff0c;提到要把减污降碳协同增效作为促…

新能源电动汽车有序充电,多场景充电解决方案-安科瑞黄安南

随着我国能源战略发展以及低碳行动的实施&#xff0c;电动汽车已逐步广泛应用&#xff0c;而电动汽车的应用非常符合当今社会对环保意识的要求&#xff0c;以及有效节省化石燃料的消耗。 由于其没有污染排放的优点以及政府部门的关注&#xff0c;电动汽车将成为以后出行的重要…

centos8安装mysql

1.首先用finalShell远程连接到服务器 2.如果服务器之前安装过mysql请先卸载,我这里是用yum安装的&#xff0c;现在通过yum去卸载 yum remove -y mysql find / -name mysql //找到残留的文件&#xff0c;再通过rm -rf去删除对应的文件3.下面正式开始安装 &#xff08;1&#…

【unity小技巧】Unity实现视差效果与无限地图(附git源码)

文章目录 前言下载素材1. 角色素材 环境搭建和人物移动视差效果无限背景源码参考完结 前言 如何提升你的画面感&#xff1f;动态的背景设计可以丰富我们的游戏效果&#xff0c;当你在游戏中行走或奔跑时&#xff0c;你将能够感受到身体在空间中的运动&#xff0c;仿佛真的置身…

成集云 | 抖店连接器客户静默下单催付数据同步钉钉 | 解决方案

源系统成集云目标系统 方案介绍 随着各品牌全渠道铺货&#xff0c;主播在平台上直播时客户下了订单后不能及时付款&#xff0c;第一时间客户收不到提醒&#xff0c;不仅造成了客户付款率下降&#xff0c;更大量消耗了企业的人力成本和经济。而成集云与钉钉深度合作&#xff0…

TouchGFX之DMA2D

Chrom-ART (DMA2D)图形加速器能够传输来自存储器的部分图像数据&#xff0c;并将其放入或先混合后再放入帧缓存。 Chrom-ART可从内部或外部存储器读取数据。 同样&#xff0c;它可以写入内部或外部存储器。 在绘制图形时可使用此功能&#xff0c;以显著提高显示性能&#xff0c…

云计算:探索现代科技的未来之云

文章目录 云计算基本概念云计算是什么注意 云计算的价值云计算的部署模式云计算的服务模式主流的云计算技术AWS简介AWS建立了广阔的合作伙伴生态 VMware简介VMware服务介绍 华为云简介华为云Stack模式 云计算基本概念 云计算是什么 云计算是一种模型&#xff0c;它可以实现随时…

VR全景:助力乡村振兴,实现可持续发展

引言&#xff1a; 随着科技的飞速发展&#xff0c;虚拟现实&#xff08;VR&#xff09;全景技术正在以惊人的速度改变着我们的生活方式和产业格局。全景技术不仅在娱乐、教育等领域取得了巨大成功&#xff0c;也为乡村振兴提供了全新的机遇。通过以乡村为背景的VR全景体验&…

微积分进阶 1.1 函数

一、函数的概念 在观察自然现象或工程实际问题时&#xff0c;我们经常发现有几个变量在变化&#xff0c;这些变量之间并不是彼此孤立的&#xff0c;而是相互制约的&#xff0c;这些变量是怎么变化的呢&#xff1f;它们之间有什么联系呢&#xff1f;存什么规律呢&#xff1f;怎…

设计模式(11)观察者模式

一、概述&#xff1a; 1、定义&#xff1a;观察者模式定义了一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象&#xff0c;使它们能够自动更新自己。 2、结构图&#xff1a; public interface S…

专用R5F+双核A53,异构多核AM64x让工控“更实时”

Cortex-R5F Cortex-A53异构多核&#xff0c; 给工控带来何种意义&#xff1f; 创龙科技SOM-TL64x工业核心板搭载TI AM64x最新工业处理器&#xff0c;因其CortexR5F 双核Cortex-A53异构多核的优良性能&#xff0c;在工业自动化、能源电力、轨道交通等领域广受客户欢迎。目前…

苍穹各种弹出框使用说明

1. 工具栏提示框 工具栏显示提示框&#xff0c;提示框有分绿色、黄色、红色的&#xff0c;代表的意义不一样。一般绿色用来提示用户操作成功&#xff1b;黄色代替这些信息是提醒、警示作用&#xff0c;不会中断用户的操作&#xff1b;而红色则表明系统出现异常。提示框的信息…

黑盒测试方法论—边界值

边界值分析法是一种很实用的黑盒测试用例方法&#xff0c;它具有很强的发现故障的能力。边界值分析法也是作为对等价类划分法的补充&#xff0c;测试用例来自等价类的边界。 这个方法其实是在测试实践当中发现&#xff0c;Bug 往往出现在定义域或值域的边界上&#xff0c;而不…

react-native(RN)实现可拖动的悬浮按钮

一、PanResponder相关知识点 PanResponder类可以将多点触摸操作协调成一个手势。它使得一个单点触摸可以接受更多的触摸操作&#xff0c;也可以用于识别简单的多点触摸手势。 默认情况下PanResponder会通过InteractionManager来阻止长时间运行的 JS 事件打断当前的手势活动。 …

JFrog Artifactory介绍

JFrog Artifactory 1. 简介2. 安装3. 使用说明3.1 界面展示3.2 仓库搭建流程&#xff08;本地库&#xff09;3.3 普通用户界面展示3.4 上传制品&#xff0c;可单传或多传3.5 下载制品3.6 支持搜索3.7 单个制品复制移动删除3.8 用户管理3.9 存储信息3.10 基本设置 4. 前期调研被…

如何使用Java可观察性进行有效编码

无论您是经验丰富的开发人员、还是数据库管理员、亦或NoSQL数据库的爱好者&#xff0c;可能已经注意到&#xff0c;在如今快速发展的企业架构格局中&#xff0c;MongoDB和Couchbase已成为NoSQL数据库的两大典型竞品。 本文将通过展示在真实企业架构中使用MongoDB和Couchbase的…