当前位置: 首页 > news >正文

QT图形视图系统 - 使用一个项目来学习QT的图形视图框架 -第一篇

文章目录

  • QT图形视图系统
    • 介绍
    • 开始搭建MainWindow框架
    • 设置scene的属性
    • 缩放功能的添加
    • 加上标尺

QT图形视图系统

介绍

详细的介绍可以看QT的官方助手,那里面介绍的详细且明白,需要一定的英语基础,我这里直接使用一个开源项目来介绍QGraphicsView、QGraphicsScene的使用。

先提供一个项目的图片

在这里插入图片描述

先来一个简单的例子,这个例子是介绍了一下QGraphicsView 和 QGraphicsScene的关系,并且如何在View中展示Scene

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>int main(int argc, char **argv)
{QApplication app(argc, argv);QGraphicsScene scene;scene.addText("Hello, QGraphicsView");QGraphicsView view(&scene);view.show();return app.exec();
}

上面的是最基本的QGraphicsView 中显示QGraphicsScene, 并且打印Hello, QGraphicsView在界面上的例子。由此我们可以看到,scene对象需要被view对象管理之后再显示出来。

接下来,我们将重写QGraphicsView 来实现我们自己要的效果。

开始搭建MainWindow框架

使用mainwindowz作为整个项目的外部界面框架,并且将自己的view放在mainwindow中

mainwindow 之后的代码我会将头文件代码和cpp代码放在一个代码块中,请注意区分

// mainwindow.h
#ifndef GRAPHICSVIEWQ_MAINWINDOW_H
#define GRAPHICSVIEWQ_MAINWINDOW_H#include <QMainWindow>
class GraphicsView;
class MainWindow : public QMainWindow
{Q_OBJECT
public:explicit MainWindow(QWidget *parent = 0);~MainWindow() override;protected:private:GraphicsView *graphics_view_;
};#endif //GRAPHICSVIEWQ_MAINWINDOW_H
// mainwindow.cpp#include <QHBoxLayout>
#include "mainwindow.h"
#include "graphicsview.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{setMouseTracking(true);resize(1600, 1000);graphics_view_ = new GraphicsView(this);graphics_view_->setObjectName(QString::fromUtf8("graphicsView"));graphics_view_->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);graphics_view_->setResizeAnchor(QGraphicsView::AnchorUnderMouse);QWidget *centralWidget = new QWidget(this);centralWidget->setObjectName(QString::fromUtf8("centralwidget"));QHBoxLayout *horizontalLayout= new QHBoxLayout(centralWidget);horizontalLayout->setSpacing(0);horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));horizontalLayout->setContentsMargins(3, 3, 3, 3);horizontalLayout->addWidget(graphics_view_);setCentralWidget(centralWidget);QGraphicsScene *scene = new QGraphicsScene();scene->addText("Hello, MainWindow");graphics_view_->setScene(scene);
}MainWindow::~MainWindow()
{}

graphicsview

// graphicsview.h
#ifndef GRAPHICSVIEWQ_GRAPHICSVIEW_H
#define GRAPHICSVIEWQ_GRAPHICSVIEW_H
#include <QGraphicsView>
#include <QWidget>class GraphicsView : public QGraphicsView
{Q_OBJECT
public:explicit GraphicsView(QWidget *parent = nullptr);explicit GraphicsView(QGraphicsScene *scene, QWidget *parent = nullptr);~GraphicsView() override;protected:private:
};
#endif //GRAPHICSVIEWQ_GRAPHICSVIEW_H
// graphicsview.cpp
#include "graphicsview.h"
GraphicsView::GraphicsView(QWidget *parent): QGraphicsView(parent)
{}GraphicsView::GraphicsView(QGraphicsScene *scene, QWidget *parent): QGraphicsView(scene, parent)
{}GraphicsView::~GraphicsView()
{}

这个时候我们展示mainwindow的时候是能正常看到 hello mainwindow的时候,我们离我们的目标又进一步了。

设置scene的属性

接下来给我们的view在构造的时候加一些属性,并且删除掉mainwindow中的scene

void GraphicsView::setBaseAttribute()
{// 设置场景QGraphicsScene *scene = new QGraphicsScene(this);scene->addText("Hello, MainWindow");setScene(scene);// 设置接收场景交互setInteractive(true);// 接收Drop事件setAcceptDrops(true);// 接收鼠标移动事件setMouseTracking(true);// CacheNone  所有的绘画都是直接在视窗上完成的.// 背景被缓存,这影响自定义背景和基于backgroundBrush属性的背景.当这个标志被启用,QGraphicsView将分配一个像素图与viewport的完整尺寸.setCacheMode(CacheBackground);// 渲染时,QGraphicsView在渲染背景或前景以及渲染每个项目时保护画家状态(参见QPainter::save())。这允许你让画工处于一个改变的状态(例如,你可以调用QPainter::setPen()或QPainter::setBrush(),而不需要在绘画后恢复状态)。但是,如果项目始终恢复状态,则应该启用此标志以防止QGraphicsView做同样的事情。setOptimizationFlag(DontSavePainterState);// 禁用QGraphicsView对曝光区域的抗锯齿自动调整。setOptimizationFlag(DontAdjustForAntialiasing);// QGraphicsView将通过分析需要重绘的区域来尝试找到最佳的更新模式。setViewportUpdateMode(SmartViewportUpdate);// 一个橡皮筋会出现。鼠标拖动将设置橡皮筋的几何形状,并选择橡皮筋覆盖的所有项目。非交互式视图禁用此模式。setDragMode(RubberBandDrag);// 设置支持鼠标右键弹出菜单setContextMenuPolicy(Qt::DefaultContextMenu);// 设置横向和纵向滚动条常开setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);// 设置黑色背景setStyleSheet("QGraphicsView { background: #000000 }");scene->setSceneRect(-1000, -1000, +2000, +2000);// 流出添加标尺的空间setViewportMargins(24, 0, 0, 24);
}

这个时候我们再运行的时候,可以看到整个背景就编程黑色的了。并且出现了滚动条

缩放功能的添加

接下来我们给界面添加缩放功能

首先我们需要注释掉黑色背景,方便我们查看文字的变化, 并且添加以下代码,以便放大缩小的时候更好的跟随鼠标

// 设置抗锯齿
setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
// 设置放大缩小的时候跟随鼠标
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
setResizeAnchor(QGraphicsView::AnchorUnderMouse);

接下来我们添加缩放函数,同时我们重写鼠标事件

void GraphicsView::zoomIn()
{if(transform().m11() > 1000.0) return;scale(zoomFactor, zoomFactor);
}void GraphicsView::zoomOut()
{if(transform().m11() < 1.0) return;scale(1.0 / zoomFactor, 1.0 / zoomFactor);
}void GraphicsView::wheelEvent(QWheelEvent *event)
{const auto delta = event->angleDelta().y();const auto pos = event->position().toPoint();static auto sbUpdate = [&delta, this, scale = 3](QScrollBar* sb) {// @TODO 如果是多个view的话 会不会出问题sb->setValue(sb->value() - delta);};if (event->buttons() & Qt::RightButton) {if (abs(delta) == 120) {setInteractive(false);if (delta > 0)zoomIn();elsezoomOut();setInteractive(true);}} else {switch (event->modifiers()) {case Qt::ControlModifier:if (abs(delta) == 120) {setInteractive(false);if (delta > 0)zoomIn();elsezoomOut();setInteractive(true);}break;case Qt::ShiftModifier:if (!event->angleDelta().x())sbUpdate(QAbstractScrollArea::horizontalScrollBar());break;case Qt::NoModifier:if (!event->angleDelta().x())sbUpdate(QAbstractScrollArea::verticalScrollBar());break;default:break;}}emit sig_mouseMove(mapToScene(pos));// QGraphicsView::wheelEvent(event);
}

通过鼠标,我们可以看到对应的变化,我这里添加了混合按钮操作,ctrl是缩放,shift是移动横轴,我这里就不贴效果图了,你们按照此步骤加函数即可,自己去尝试效果去吧。

我们还需要回到最初始的大小,这个时候我们需要添加回到100%比例的函数。并且添加一个键盘事件,按下空格的时候则回到100%的状态。这里可以在初始化的时候直接给设置成百分百

QSizeF GraphicsView::getRealSize() 
{static QSizeF size;if (!size.isEmpty())return size;if (size.isEmpty()) FIXME 当前界面的物理尺寸size = QGuiApplication::screens()[0]->physicalSize();return size;
}void GraphicsView::zoomTo100()
{
 根据物理尺寸设置大小, 因为后面我们会引入尺子,因此这里设置为根据物理尺寸设置double x = 1.0, y = 1.0;const double m11 = QGraphicsView::transform().m11(), m22 = QGraphicsView::transform().m22();const double dx = QGraphicsView::transform().dx(), dy = QGraphicsView::transform().dy();const QSizeF size(getRealSize());                                      // size in mmconst QRect scrGeometry(QApplication::primaryScreen()->geometry()); // size in pixx = qAbs(1.0 / m11 / (size.height() / scrGeometry.height()));y = qAbs(1.0 / m22 / (size.width() / scrGeometry.width()));std::cout << dx << " " << dy << std::endl;scale(x, y); 恢复到初始状态(位移状态未记录)
//    QMatrix q;
//    q.setMatrix(1,this->matrix().m12(),this->matrix().m21(),1,this->matrix().dx(),this->matrix().dy());
//    this->setMatrix(q,false);
}void GraphicsView::keyPressEvent(QKeyEvent *event)
{switch (event->key()) {case Qt::Key_Space:zoomTo100();break;case Qt::Key_F:zoomFit();break;default:break;}QGraphicsView::keyPressEvent(event);
}void GraphicsView::zoomFit()
{fitInView(scene()->itemsBoundingRect(), false);
}void GraphicsView::fitInView(QRectF dstRect, bool withBorders)
{if (dstRect.isNull())return;if (withBorders)dstRect += QMarginsF(dstRect.width() / 5, dstRect.height() / 5, dstRect.width() / 5, dstRect.height() / 5); // 5 mmQGraphicsView::fitInView(dstRect, Qt::KeepAspectRatio);
}

加上标尺

接下来我们来给我们的视图加上左边和下面的标尺

先上一张图片

在这里插入图片描述

ruler

#ifndef GRAPHICSVIEWLEARN_RULER_H
#define GRAPHICSVIEWLEARN_RULER_H#include <QWidget>
#include <QPen>class Ruler final : public QWidget
{Q_OBJECT
public:enum { Width = 24};explicit Ruler(Qt::Orientation rulerType, QWidget* parent);void drawAScaleMeter(QPainter* painter, QRectF rulerRect, double scaleMeter, double startPosition);// 绘制刻度线void drawFromOriginTo(QPainter* painter, QRectF rect, double startMark, double endMark, int startTickNo, double step, double startPosition);protected:void paintEvent(QPaintEvent* event) override;void drawMousePosTick(QPainter* painter);private:Qt::Orientation orientation_;double grid_step_ {1.0};double origin_ {};double ruler_unit_ {1.0};double ruler_zoom_ {1.0};double tick_koef_ {1.0};QPoint cursor_pos_;QPen meter_pen_;bool draw_text_ {};
};#endif //GRAPHICSVIEWLEARN_RULER_H#include "ruler.h"
#include <QPainter>Ruler::Ruler(Qt::Orientation rulerType, QWidget *parent): QWidget(parent), orientation_ { rulerType }
{setMouseTracking(true);setStyleSheet("QWidget{ background:black; }");
}void Ruler::paintEvent(QPaintEvent *event)
{Q_UNUSED(event)QPainter painter(this);painter.setRenderHints(QPainter::TextAntialiasing);painter.setPen(QPen(Qt::darkGray, 0.0)); // 零宽度笔是装饰笔QRectF rulerRect(rect()); // 需要QRectF// 首先填充矩形painter.fillRect(rulerRect, QColor().rgb());if (qFuzzyIsNull(ruler_zoom_))return;// fixme 这个地方需要修改成带单位转换的grid_step_ = pow(10.0, ceil(log10(8.0 / ruler_zoom_)));// ViewSettings::instance().gridStep(rulerZoom_);// 绘制小刻度if ((grid_step_ * ruler_zoom_) > 35) {tick_koef_ = 0.1;draw_text_ = true;}meter_pen_ = QPen(Qt::darkGray, 0.0);drawAScaleMeter(&painter, rulerRect, grid_step_ * 1, static_cast<double>(Ruler::Width) * 0.6);draw_text_ = false;// 绘制中间刻度if ((grid_step_ * ruler_zoom_) <= 35) {tick_koef_ = 0.5;draw_text_ = true;}meter_pen_ = QPen(Qt::green, 0.0);drawAScaleMeter(&painter, rulerRect, grid_step_ * 5, static_cast<double>(Ruler::Width) * 0.3);draw_text_ = false;// 绘制整刻度线meter_pen_ = QPen(Qt::red, 0.0);drawAScaleMeter(&painter, rulerRect, grid_step_ * 10, static_cast<double>(Ruler::Width) * 0);// 绘制当前鼠标位置十字线drawMousePosTick(&painter);// 在视图和标尺之间分割线 红色的线(看是否需要)if ((1)) {QPointF starPt((Qt::Horizontal == orientation_) ? rulerRect.topLeft() : rulerRect.topRight());QPointF endPt((Qt::Horizontal == orientation_) ? rulerRect.topRight() : rulerRect.bottomRight()); // FIXME same branches!!!!!!painter.setPen(QPen(Qt::red, 2));painter.drawLine(starPt, endPt);}QWidget::paintEvent(event);
}void Ruler::drawAScaleMeter(QPainter* painter, QRectF rulerRect, double scaleMeter, double startPosition)
{bool isHorzRuler = Qt::Horizontal == orientation_;scaleMeter = scaleMeter * ruler_unit_ * ruler_zoom_;double rulerStartMark = isHorzRuler ? rulerRect.left() : rulerRect.top();// Ruler rectangle ending markdouble rulerEndMark = isHorzRuler ? rulerRect.right() : rulerRect.bottom();if (origin_ >= rulerStartMark && origin_ <= rulerEndMark) {drawFromOriginTo(painter, rulerRect, origin_, rulerEndMark, 0, scaleMeter, startPosition);drawFromOriginTo(painter, rulerRect, origin_, rulerStartMark, 0, -scaleMeter, startPosition);} else if (origin_ < rulerStartMark) {int tickNo = int((rulerStartMark - origin_) / scaleMeter);drawFromOriginTo(painter, rulerRect, origin_ + scaleMeter * tickNo,rulerEndMark, tickNo, scaleMeter, startPosition);} else if (origin_ > rulerEndMark) {int tickNo = int((origin_ - rulerEndMark) / scaleMeter);drawFromOriginTo(painter, rulerRect, origin_ - scaleMeter * tickNo,rulerStartMark, tickNo, -scaleMeter, startPosition);}
}void Ruler::drawFromOriginTo(QPainter* painter, QRectF rect, double startMark, double endMark, int startTickNo, double step, double startPosition)
{const auto isHorzRuler = (Qt::Horizontal == orientation_);// fixme 这个地方要修改成单位转换的const auto K = grid_step_ * tick_koef_ * 1.0;QColor color(0xFFFFFFFF - QColor(Qt::black).rgb());painter->setPen(QPen(color, 0.0));painter->setFont(font());QVector<QLineF> lines;lines.reserve(abs(ceil((endMark - startMark) / step)));constexpr double padding = 3;for (double current = startMark; (step < 0 ? current >= endMark : current <= endMark); current += step) {double x1, y1;lines.push_back(QLineF(x1 = isHorzRuler ? current : rect.left() + startPosition,y1 = isHorzRuler ? rect.top() : current,/*x2*/ isHorzRuler ? current : rect.right(),/*y2*/ isHorzRuler ? rect.bottom() - startPosition : current));if (draw_text_) {painter->save();auto number { QString::number(startTickNo * K) };if (startTickNo)number = ((isHorzRuler ^ (step > 0.0)) ? "-" : "+") + number;QRectF textRect(QFontMetricsF(font()).boundingRect(number));textRect.setWidth(textRect.width() + 1);if (isHorzRuler) {painter->translate(x1 + padding, textRect.height());painter->drawText(textRect, Qt::AlignCenter, number);} else {painter->translate(textRect.height() - padding, y1 - padding);painter->rotate(-90);painter->drawText(textRect, number);}painter->restore();}++startTickNo;}painter->setPen(meter_pen_);painter->drawLines(lines.data(), lines.size());
}void Ruler::drawMousePosTick(QPainter* painter)
{QPoint starPt = cursor_pos_;QPoint endPt;if (Qt::Horizontal == orientation_) {starPt.setY(this->rect().top());endPt.setX(starPt.x());endPt.setY(this->rect().bottom());} else {starPt.setX(this->rect().left());endPt.setX(this->rect().right());endPt.setY(starPt.y());}painter->drawLine(starPt, endPt);
}

好了,本篇先介绍到这里,接下来我会写下一篇,让我们一起去实现后续的效果。

相关文章:

QT图形视图系统 - 使用一个项目来学习QT的图形视图框架 -第一篇

文章目录 QT图形视图系统介绍开始搭建MainWindow框架设置scene的属性缩放功能的添加加上标尺 QT图形视图系统 介绍 详细的介绍可以看QT的官方助手&#xff0c;那里面介绍的详细且明白&#xff0c;需要一定的英语基础&#xff0c;我这里直接使用一个开源项目来介绍QGraphicsVi…...

Cat.1如何成为物联网业务加速器?

随着Cat.1芯片及模组在功耗和成本上的不断优化&#xff0c;在窄带物联网领域&#xff0c;越来越多的终端客户把Cat.1当做与NB-IoT相比较的第二选择。越来越多的表计、烟感、市政等行业终端将Cat.1模组应用于非集中化部署的上报类终端业务中&#xff0c;Cat.1这只“网红猫”仍保…...

Qt应用开发(基础篇)——布局管理 Layout Management

目录 一、前言 二&#xff1a;相关类 三、水平、垂直、网格和表单布局 四、尺寸策略 一、前言 在实际项目开发中&#xff0c;经常需要使用到布局&#xff0c;让控件自动排列&#xff0c;不仅节省控件还易于管控。Qt布局系统提供了一种简单而强大的方式来自动布局小部件中的…...

Python web实战之 Django 的 ORM 框架详解

本文关键词&#xff1a;Python、Django、ORM。 概要 在 Python Web 开发中&#xff0c;ORM&#xff08;Object-Relational Mapping&#xff0c;对象关系映射&#xff09;是一个非常重要的概念。ORM 框架可以让我们不用编写 SQL 语句&#xff0c;就能够使用对象的方式来操作数据…...

pycharm制作柱状图

Bar - Bar_rotate_xaxis_label 解决标签名字过长的问题 from pyecharts import options as opts from pyecharts.charts import Barc (Bar().add_xaxis(["高等数学1&#xff0c;2","C语言程序设计","python程序设计","大数据导论",…...

静态资源导入探究

静态资源可以在哪里找呢&#xff1f;我们看看源码 从这个类进去 里面有个静态类 WebMvcAutoConfigurationAdapter 有个配置类&#xff0c;将这个类的对象创建并导入IOC容器里 这个静态类下有个方法 addResourceHandlers(ResourceHandlerRegistry registry)静态资源处理器 若自…...

安全狗V3.512048版本绕过

安全狗安装 安全狗详细安装、遇见无此服务器解决、在windows中命令提示符中进入查看指定文件夹手动启动Apache_安全狗只支持 glibc_2.14 但是服务器是2.17_黑色地带(崛起)的博客-CSDN博客 安全狗 safedogwzApacheV3.5.exe 右键电脑右下角安全狗图标-->选择插件-->安装…...

prometheus监控k8s kube-proxy target down

prometheus kube-proxy target down 解决 修改配置 kubectl edit cm/kube-proxy -n kube-systemmetricsBindAddress: "0.0.0.0:10249"删除 kube-proxy pod 使之重启应用配置 kubectl delete pod --force `kubectl get pod -n kube-system |grep kube-proxy|awk {pr…...

SPSS数据分析--假设检验的两种原假设取舍决定方式

假设检验的两种原假设取舍决定方式 在t检验&#xff0c;相关分析&#xff0c;回归分析&#xff0c;方差分析&#xff0c;卡方检验等等分析方法中&#xff0c;都需要用到假设检验。假设检验的步骤一般如下&#xff1a; 提出假设&#xff1a;H0 vs H1 ;假设原假设H0 成立的情况…...

Python实现猫狗分类

不废话了&#xff0c;直接上代码&#xff1a; def load_imagepath_from_csv(csv_name):image_path []with open(csv_name,r) as file:csv_reader csv.reader(file)next(csv_reader)for row in csv_reader:image_path.append(row[0])return image_pathimport csv csv_name &…...

pjsip、pjsua2+bcg729 windows下编译java版本

文章目录 简要说明流程步骤 简要说明 基本参考的这里 https://docs.pjsip.org/en/latest/get-started/windows/build_instructions.html#building-the-projects 我这里主要是为了生成pjsua2.dll 用于在java下调用。 其中 libbcg729.dll 是通过vcpkg来进行安装。 pjsip使用vs2…...

尝试多数据表 sqlite

C 唯一值得骄傲的地方就是 通过指针来回寻址 &#x1f602; 提高使用的灵活性 小脚本buff 加成...

Keil出现Flash Timeout.Reset the Target and try it again.我有一种解决方法

2.解决方法 网上查找了找原因&#xff0c;是因为之前代码设置了读保护功能。 读保护即大家通常说的“加密”&#xff0c;是作用于整个Flash存储区域。一旦设置了Flash的读保护&#xff0c;内置的Flash存储区只能通过程序的正常执行才能读出&#xff0c;而不能通过下述任何一种…...

纯粹即刻,畅享音乐搜索的轻松体验

纯粹即刻&#xff0c;畅享音乐搜索的轻松体验 在当今快节奏的生活中&#xff0c;我们常常渴望一种简单而便捷的方式来探索和享受音乐。现在&#xff0c;你可以纯粹即刻地畅享音乐搜索的轻松体验。无论你是寻找热门歌曲还是探索不同风格的音乐&#xff0c;这款应用将为你带来随…...

动态规划之树形DP

动态规划之树形DP 树形DP何为树形DP 树形DP例题HDU-1520 Anniversary partyHDU-2196 Computer834. 树中距离之和 树形DP 何为树形DP 树形DP是指在“树”这种数据结构上进行的动态规划&#xff1a;给出一颗树&#xff0c;要求以最少的代价&#xff08;或取得最大收益&#xff…...

嵌入式_GD32使用宏开关进行Debug串口打印调试

嵌入式_GD32使用宏开关进行Debug串口打印调试 串口Debug是一种将数据通过串口发送的方法。通过使用printf函数&#xff0c;我们可以将需要发送的数据格式化为字符串&#xff0c;并通过串口发送出去。在C语言中&#xff0c;通常使用串口发送数据的函数为printf函数&#xff0c;…...

使用 GitHub Copilot 进行 Prompt Engineering 的初学者指南(译)

文章目录 什么是 GitHub Copilot ?GitHub Copilot 可以自己编码吗&#xff1f;GitHub Copilot 的底层是如何工作的&#xff1f;什么是 prompt engineering?这是 prompt engineering 的另一个例子 使用 GitHub Copilot 进行 prompt engineering 的最佳实践提供高级上下文&…...

c++开发模式,享元模式

享元模式&#xff0c;个人理解&#xff0c;就是应用共享技术来减少类的对象创建&#xff0c;节省计算机资源消耗&#xff0c;而且能够减少维护成本 #include <iostream> #include <string> #include <vector>using namespace std;class Flyweight { public:…...

LLM大模型——langchain相关知识总结

目录 一、简介LangChain的主要价值支柱简单安装 二、 LangChain的主要模块1.Model I/Oprompt模版定义调用语言模型 2. 数据连接3. chains4. Agents5. MemoryCallbacks 三、其他记录多进程调用 主要参考以下开源文档 文档地址&#xff1a;https://python.langchain.com/en/lates…...

【Python】数据可视化利器PyCharts在测试工作中的应用

目录 PyCharts 简介 PyCharts 的安装 缺陷统计 测试用例执行情况 使用JavaScript情况 缺陷趋势分析 将两张图放在一个组合里&#xff08;grid&#xff09; 将两张图重叠成一张图&#xff08;overlap&#xff09; 将多张图组合在一个page 中&#xff08;page&#xff0…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

docker 部署发现spring.profiles.active 问题

报错&#xff1a; org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...