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

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

回溯算法学习

一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...