当前位置: 首页 > 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…...

AOP的实战(统一功能处理模块)

一、用户登录权限效验 用户登录权限的发展从之前每个方法中自己验证用户登录权限&#xff0c;到现在统一的用户登录验证处理&#xff0c;它是一个逐渐完善和逐渐优化的过程。 1.1 最初用户登录验证 我们先来回顾一下最初用户登录验证的实现方法&#xff1a; RestController…...

时间复杂度为O(n2)的三种简单排序算法

1.冒泡排序 冒泡排序只会操作相邻的两个数据。每次冒泡操作都会对相邻的两个元素进行比较&#xff0c;看是否满足大小关系要求。如果不满足就让它俩互换。一次冒泡会让至少少一个元素移动到它应该在的位置&#xff0c;重复n次&#xff0c;就完成了n个数据的排序工作。 /*** …...

LeetCode 热题 100 JavaScript --226. 翻转二叉树

给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 3&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[] 提示&#xff1a; 树中节点数目范围在 [0, 100] 内 -100 < Node.val < 100 var invertTree function(root…...

hive所有窗口函数详情总结

hive窗口函数详情总结 解释语法hive开窗函数排序开窗函数样例数据RANK()DENSE_RANK()ROW_NUMBER() 分析开窗函数样例数据&#xff1a;last_valuefirst_valuelaglead 其他窗口函数cume_distpercent_rank 解释 开窗函数用于为行定义一个窗口&#xff08;指运算将要操作的行的集合…...

Talk | 新加坡国立大学博士生施宇钧:DragDiffusion-基于扩散模型的关键点拖拽图片编辑

本期为TechBeat人工智能社区第518期线上Talk&#xff01; 北京时间8月2日(周三)20:00&#xff0c; 新加坡国立大学博士生—施宇钧的Talk已准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “DragDiffusion-基于扩散模型的关键点拖拽图片编辑”&#xff0c;他…...

22 | 贝叶斯分类算法

文章目录 介绍什么是贝叶斯分类算法?贝叶斯分类算法的应用场景贝叶斯定理贝叶斯定理的基本原理贝叶斯定理的公式推导贝叶斯定理的应用举例代码介绍 什么是贝叶斯分类算法? 贝叶斯分类算法是一类基于贝叶斯定理的分类技术。在统计分类任务中,这些算法使用特定的假设来建立特…...

java.sql.SQLSyntaxErrorException: ORA-00909: 参数个数无效

问题&#xff1a; 在Select里采用Contact(%,#name,%)报错参数个数无效 原因&#xff1a; 回想以前用Mysql的时候就是这样用的&#xff0c;没有问题&#xff0c;在这里就出问题了&#xff0c;所以确定问题在oracle数据库上&#xff0c;经过查询得知&#xff0c;oracle和mysql…...

数据结构8-哈希表

数据结构8-哈希表 动态分配内存方式&#xff1a; #include <stdio.h> #include <stdlib.h>#define SIZE 20struct DataItem {int data; int key; };struct DataItem* hashArray[SIZE]; struct DataItem* dummyItem; struct DataItem* item;//获取键值 int has…...

vue3引用Font-Awesome字体图标库

环境&#xff1a;vue3tsviteelement plus 介绍&#xff1a;这里安装引用的是Font-Awesome 6.x 版本&#xff0c;有专业版&#xff08;付费&#xff09;&#xff0c;这里只介绍免费版字体使用方法 一、安装 1.使用npm安装&#xff0c;终端打开项目目录或者命令行cd到目录文件夹…...

Python: Django 服务部署可能遇到的一些问题

502 bad gateway 不要用 python3 manage.py runserver 启动服务&#xff0c; 而要用&#xff1a; daphne -b 0.0.0.0 -p <端口> <工程名>.asgi:application此外&#xff0c;在 setting.py 中&#xff0c;修改&#xff1a; import osSECRET_KEY os.environ.get(D…...