[QCustomPlot] 交互示例 Interaction Example

news2025/1/13 19:12:30

本文是官方例子的分析: Interaction Example
推荐笔记: qcustomplot使用教程–基本绘图
推荐笔记: 4.QCustomPlot使用-坐标轴常用属性

在这里插入图片描述

  • 官方例子需要用到很多槽函数, 这里先一次性列举, 自行加入到qt.h中.下面开始从简单的开始一个个分析.
    void qcustomplot_main_init(void);       // 初始化
    void titleDoubleClick(QMouseEvent* event); // 标题 双击
    void axisLabelDoubleClick(QCPAxis *axis, QCPAxis::SelectablePart part); // 标签 双击
    void legendDoubleClick(QCPLegend *legend, QCPAbstractLegendItem *item); // 图例 双击
    void selectionChanged(void);            // 选择已更改
    void mousePress(void);                  // 鼠标按下
    void mouseWheel(void);                  // 鼠标滚轮
    void addRandomGraph(void);              // 添加随机图
    void removeSelectedGraph(void);         // 删除选定图形
    void removeAllGraphs(void);             // 删除所有图形
    void contextMenuRequest(QPoint pos);    // 上下文菜单请求
    void moveLegend(void);                  // 移动图例
    void graphClicked(QCPAbstractPlottable *plottable, int dataIndex); // 图表点击

1.图表点击

// 图表点击
void MainWindow::graphClicked(QCPAbstractPlottable *plottable, int dataIndex)
{
    //由于我们知道图中只有QCPG图,我们可以立即访问interface1D()
    //通常最好先检查interface1D()是否返回非零,然后再使用它。

    // plottable 表示绘图中对象的所有数据的抽象基类。更多。。。

    // 如果此plottable是一维plottable,即它实现了QCPPlottableInterface1D,则返回具有该类型的this指针。否则(例如在QCPColorMap的情况下)返回零。
    // interface1D() 您可以使用此方法获得对数据坐标的读取权限,同时只持有指向抽象基类的指针。

    // dataMainValue() 返回给定索引处数据点的主值。 主要值是什么,由plottable的数据类型定义。

    double dataValue = plottable->interface1D()->dataMainValue(dataIndex);
    QString message = QString("Clicked on graph '%1' at data point #%2 with value %3.").arg(plottable->name()).arg(dataIndex).arg(dataValue);
    // ui->statusBar->showMessage(message, 2500);
    qDebug() << message;
}
  • 当鼠标点击图标中的曲线时, 会回调该函数, 函数内可以获取曲线的名称和数据等. 并打印出最近的点坐标. 如果之后要显示文本游标,可以在这里显示;

2.移动图例

// 图像 移动图例
void MainWindow::moveLegend(void)
{
    QCustomPlot * customPlot = ui->customPlot;

    // 确保此插槽确实由上下文菜单操作调用,以便它携带我们需要的数据
    if (QAction* contextAction = qobject_cast<QAction*>(sender())) // 通过上下文菜单传入
    {
        bool ok;
        int dataInt = contextAction->data().toInt(&ok); // 获取传入的参数
        if (ok) // 数据解析正确, 这里应该添加确保位置枚举正确
        {
            customPlot->axisRect()->insetLayout()->setInsetAlignment(0, static_cast<Qt::Alignment>(dataInt)); // 设置图例的位置
            customPlot->replot(); // 重绘图像
        }
    }
}
  • 这个函数是用于移动图例时调用, 在右键菜单中点击选项后调用.

3.右键菜单/上下文菜单请求

// 图像 上下文菜单请求
void MainWindow::contextMenuRequest(QPoint pos)
{
    QCustomPlot * customPlot = ui->customPlot;

    QMenu *menu = new QMenu(this);              // 创建一个菜单
    menu->setAttribute(Qt::WA_DeleteOnClose);   // 当小部件接受关闭事件时,使Qt删除此小部件

    if (customPlot->legend->selectTest(pos, false) >= 0) // 请求图例的上下文菜单, 调用了上一个移动图例函数
    {
        menu->addAction("Move to top left", this, SLOT(moveLegend()))->setData(static_cast<int>(Qt::AlignTop|Qt::AlignLeft));           // 移动图例到左上角
        menu->addAction("Move to top center", this, SLOT(moveLegend()))->setData(static_cast<int>(Qt::AlignTop|Qt::AlignHCenter));      // 移动图例到中上角
        menu->addAction("Move to top right", this, SLOT(moveLegend()))->setData(static_cast<int>(Qt::AlignTop|Qt::AlignRight));         // 移动图例到右上角
        menu->addAction("Move to bottom right", this, SLOT(moveLegend()))->setData(static_cast<int>(Qt::AlignBottom|Qt::AlignRight));   // 移动图例到左下角
        menu->addAction("Move to bottom left", this, SLOT(moveLegend()))->setData(static_cast<int>(Qt::AlignBottom|Qt::AlignLeft));     // 移动图例到右下角
    }
    else  // 所需图形上的通用上下文菜单
    {
        menu->addAction("Add random graph", this, SLOT(addRandomGraph()));                  // 添加一条曲线
        if (customPlot->selectedGraphs().size() > 0)                                        // 如果选择的曲线数量大于0
            menu->addAction("Remove selected graph", this, SLOT(removeSelectedGraph()));    // 删除曲线
        if (customPlot->graphCount() > 0)                                                   // 如果全部曲线数量大于0
            menu->addAction("Remove all graphs", this, SLOT(removeAllGraphs()));            // 删除所有曲线
    }

    // 将小部件坐标pos转换为全局屏幕坐标。例如,mapToGlobal(QPoint(0,0))将给出小部件左上角像素的全局坐标。
    // 显示菜单,使动作atAction位于指定的全局位置p。要将小部件的局部坐标转换为全局坐标,
    menu->popup(customPlot->mapToGlobal(pos));
}
  • 在图像内右键时调用, 设定弹出的上下文菜单.
  • 先是判断点击位置是否在图例内, 如果是就弹出图例菜单, 否者就弹出曲线菜单;注意
  • 注意选择 菜单后调用的函数,传参的方法.

4.删除所有曲线

// 图像 删除所有图形
void MainWindow::removeAllGraphs()
{
    QCustomPlot * customPlot = ui->customPlot;

    customPlot->clearGraphs();  // 删除所有曲线, 坐标轴等内容是保留的
    customPlot->replot();       // 重绘图像
}
  • 注意是删除所有graphs,我发现其他例子中貌似有些曲线不算graphs;

5.删除选择曲线

// 图像 删除选定图形
void MainWindow::removeSelectedGraph()
{
    QCustomPlot * customPlot = ui->customPlot;

    if (customPlot->selectedGraphs().size() > 0) // 选择的曲线数量大于0
    {
        customPlot->removeGraph(customPlot->selectedGraphs().first()); // 删除特定的曲线, 选择曲线列表中的第一条
        customPlot->replot(); // 重绘图像
    }
}

6.添加随机曲线

// 图像 添加图像
void MainWindow::addRandomGraph()
{
    QCustomPlot * customPlot = ui->customPlot;

    int n = 50; // 图中的点数
    double xScale = (rand()/static_cast<double>(RAND_MAX) + 0.5)*2;
    double yScale = (rand()/static_cast<double>(RAND_MAX) + 0.5)*2;
    double xOffset = (rand()/static_cast<double>(RAND_MAX) - 0.5)*4;
    double yOffset = (rand()/static_cast<double>(RAND_MAX) - 0.5)*10;
    double r1 = (rand()/static_cast<double>(RAND_MAX) - 0.5)*2;
    double r2 = (rand()/static_cast<double>(RAND_MAX) - 0.5)*2;
    double r3 = (rand()/static_cast<double>(RAND_MAX) - 0.5)*2;
    double r4 = (rand()/static_cast<double>(RAND_MAX) - 0.5)*2;
    QVector<double> x(n), y(n);
    for (int i=0; i<n; i++)
    {
        x[i] = (i/static_cast<double>(n)-0.5)*10.0*xScale + xOffset;
        y[i] = (qSin(x[i]*r1*5)*qSin(qCos(x[i]*r2)*r4*3)+r3*qCos(qSin(x[i])*r4*2))*yScale + yOffset;
    }

    customPlot->addGraph(); // 添加曲线
    customPlot->graph()->setName(QString("New graph %1").arg(customPlot->graphCount()-1)); // 设置曲线图例名字
    customPlot->graph()->setData(x, y); // 设置数据
    customPlot->graph()->setLineStyle(static_cast<QCPGraph::LineStyle>(rand()%5+1)); // 设置曲线类型
    if (rand()%100 > 50)
        customPlot->graph()->setScatterStyle(QCPScatterStyle(static_cast<QCPScatterStyle::ScatterShape>(rand()%14+1))); // 设置点的类型
    QPen graphPen;
    graphPen.setColor(QColor(rand()%245+10, rand()%245+10, rand()%245+10)); // 设置颜色
    graphPen.setWidthF(rand()/static_cast<double>(RAND_MAX)*2+1); // 设置粗细
    customPlot->graph()->setPen(graphPen); // 设置线的颜色等
    customPlot->replot(); // 重绘
}
  • 这就是添加一些随机数据然后显示.设置了图线的显示样式;

7.鼠标滚轮缩放图像

// 图像 鼠标滚轮
void MainWindow::mouseWheel()
{
    QCustomPlot * customPlot = ui->customPlot;
    
    //如果选择了一个轴,则只允许缩放该轴的方向
    //如果未选择轴,则可以缩放两个方向

    if (customPlot->xAxis->selectedParts().testFlag(QCPAxis::spAxis))               // 如果选择了坐标轴
        customPlot->axisRect()->setRangeZoom(customPlot->xAxis->orientation());     // 只缩放一个坐标轴
    else if (customPlot->yAxis->selectedParts().testFlag(QCPAxis::spAxis))          // 如果选择了坐标轴
        customPlot->axisRect()->setRangeZoom(customPlot->yAxis->orientation());     // 只缩放一个坐标轴
    else
        customPlot->axisRect()->setRangeZoom(Qt::Horizontal|Qt::Vertical);          // 同时缩放两个坐标轴
}
  • 通过点击坐标来判断选择坐标轴的缩放,非常好的思路,就是不太习惯;

8.鼠标按下移动图像

// 图像 鼠标被按下
void MainWindow::mousePress()
{
    QCustomPlot * customPlot = ui->customPlot;

    //如果选择了轴,则只允许拖动该轴的方向
    //如果未选择轴,则可以拖动两个方向

    if (customPlot->xAxis->selectedParts().testFlag(QCPAxis::spAxis))                 // 如果选择了坐标轴
        customPlot->axisRect()->setRangeDrag(customPlot->xAxis->orientation());       // 只移动一个坐标轴
    else if (customPlot->yAxis->selectedParts().testFlag(QCPAxis::spAxis))            // 如果选择了坐标轴
        customPlot->axisRect()->setRangeDrag(customPlot->yAxis->orientation());       // 只移动一个坐标轴
    else
        customPlot->axisRect()->setRangeDrag(Qt::Horizontal|Qt::Vertical);            // 同时移动两个坐标轴
}

9.选择坐标轴或图例或曲线

// 图像 选择被修改
void MainWindow::selectionChanged(void)
{
    QCustomPlot * customPlot = ui->customPlot;

    /*
    通常,坐标轴基线、坐标轴刻度标签和坐标轴标签是可以单独选择的,但我们希望用户只能将整个坐标轴作为一个整体来选择,因此我们将刻度标签和坐标轴基线的选中状态绑定在一起。然而,坐标轴标签仍然可以单独选择。

    左侧和右侧坐标轴的选中状态应该同步,底部和顶部坐标轴的选中状态也应该同步。

    此外,我们希望将图形的选中状态与其对应的图例项的选中状态同步。这样,用户既可以通过点击图形本身来选择图形,也可以通过点击其图例项来选择图形。
    */

    //使上下轴同步选择,并将轴和刻度标签作为一个可选对象处理:
    if (customPlot->xAxis->selectedParts().testFlag(QCPAxis::spAxis) || customPlot->xAxis->selectedParts().testFlag(QCPAxis::spTickLabels) ||
        customPlot->xAxis2->selectedParts().testFlag(QCPAxis::spAxis) || customPlot->xAxis2->selectedParts().testFlag(QCPAxis::spTickLabels))
    {
        customPlot->xAxis2->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels); // 如果其中一边坐标轴被选择, 那另一边的坐标轴也被同步选择
        customPlot->xAxis->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
    }

    //使左右轴同步选择,并将轴和刻度标签作为一个可选对象处理:
    if (customPlot->yAxis->selectedParts().testFlag(QCPAxis::spAxis) || customPlot->yAxis->selectedParts().testFlag(QCPAxis::spTickLabels) ||
        customPlot->yAxis2->selectedParts().testFlag(QCPAxis::spAxis) || customPlot->yAxis2->selectedParts().testFlag(QCPAxis::spTickLabels))
    {
        customPlot->yAxis2->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels); // 如果其中一边坐标轴被选择, 那另一边的坐标轴也被同步选择
        customPlot->yAxis->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
    }

    //将图形的选择与相应图例项的选择同步:
    for (int i=0; i<customPlot->graphCount(); ++i)
    {
        QCPGraph *graph = customPlot->graph(i); // 获取图像对象
        QCPPlottableLegendItem *item = customPlot->legend->itemWithPlottable(graph); // 获取图例对象
        if (item->selected() || graph->selected()) // 如果图例或图像被选择, 就同步两个都被选择
        {
            item->setSelected(true);
            graph->setSelection(QCPDataSelection(graph->data()->dataRange()));
        }
    }
}
  • 用于同步选择对象, 选择了一边坐标轴就同时设置另一边也被选择.图例和曲线同理;
  • 注意函数的调用,暂时无法理解的话就照抄微改;

10.双击图例修改名字

// 图像 图例双击
void MainWindow::legendDoubleClick(QCPLegend *legend, QCPAbstractLegendItem *item)
{
    QCustomPlot * customPlot = ui->customPlot;

    //双击图例项重命名图形
    Q_UNUSED(legend) // 消除报错
    if (item) //仅当项目被点击时才会做出反应(用户本可以在没有项目的地方点击图例的边框填充,则项目为0)
    {
        QCPPlottableLegendItem *plItem = qobject_cast<QCPPlottableLegendItem*>(item); // 对象类型转换
        bool ok;
        QString newName = QInputDialog::getText(this, "QCustomPlot example", "New graph name:", QLineEdit::Normal, plItem->plottable()->name(), &ok); // 使用弹窗获取文本
        if (ok) // 获取成功
        {
            plItem->plottable()->setName(newName); // 重新设置图例名字
            customPlot->replot(); // 重绘图像
        }
    }
}
  • 注意函数调用,其他不赘述了;

11.双击坐标轴修改名字

// 图像 标签双击
void MainWindow::axisLabelDoubleClick(QCPAxis *axis, QCPAxis::SelectablePart part)
{
    QCustomPlot * customPlot = ui->customPlot;

    // Set an axis label by double clicking on it
    if (part == QCPAxis::spAxisLabel) // only react when the actual axis label is clicked, not tick label or axis backbone
    {
        bool ok;
        QString newLabel = QInputDialog::getText(this, "QCustomPlot example", "New axis label:", QLineEdit::Normal, axis->label(), &ok);
        if (ok)
        {
            axis->setLabel(newLabel);
            customPlot->replot();
        }
    }
}
  • 注意函数调用,和上一个功能类似,其他不赘述了;

12.双击标题修改名字

// 图像 标题双击
void MainWindow::titleDoubleClick(QMouseEvent* event)
{
    QCustomPlot * customPlot = ui->customPlot;

    Q_UNUSED(event)
    if (QCPTextElement *title = qobject_cast<QCPTextElement*>(sender()))
    {
        // Set the plot title by double clicking on it
        bool ok;
        QString newTitle = QInputDialog::getText(this, "QCustomPlot example", "New plot title:", QLineEdit::Normal, title->text(), &ok);
        if (ok)
        {
            title->setText(newTitle);
            customPlot->replot();
        }
    }
}
  • 注意函数调用,和上一个功能类似,其他不赘述了;

13.初始化图表内容

// 图像 初始化
void MainWindow::qcustomplot_main_init(void)
{
    QCustomPlot * customPlot = ui->customPlot; // 方便调用

    customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes | QCP::iSelectLegend | QCP::iSelectPlottables); // 允许拖动,缩放,选择坐标轴,选择图例,选择曲线;
    customPlot->xAxis->setRange(-8, 8);         // 设置初始范围
    customPlot->yAxis->setRange(-5, 5);         // 设置初始范围
    customPlot->axisRect()->setupFullAxesBox(); // 相当于开启右和上的坐标轴, 方便功能,在每侧创建一个还没有轴的轴,并将其可见性设置为true。此外,顶部/右侧轴被分配了底部/左侧轴的以下属性:

    customPlot->plotLayout()->insertRow(0);     // 插入一行?
    QCPTextElement *title = new QCPTextElement(customPlot, "Interaction Example", QFont("sans", 17, QFont::Bold));
    customPlot->plotLayout()->addElement(0, 0, title); // 在上面插入的那一行中? 添加标题

    customPlot->xAxis->setLabel("x Axis"); // 设置坐标轴名字
    customPlot->yAxis->setLabel("y Axis");
    customPlot->legend->setVisible(true); // 显示图例
    QFont legendFont = font();
    legendFont.setPointSize(10); // 设置字体大小
    customPlot->legend->setFont(legendFont);  // 设置字体
    customPlot->legend->setSelectedFont(legendFont); // 设置选择后的字体
    customPlot->legend->setSelectableParts(QCPLegend::spItems); // 图例框不可选择,只能选择图例项

    addRandomGraph(); // 添加随机曲线
    addRandomGraph();
    addRandomGraph();
    addRandomGraph();
    customPlot->rescaleAxes(); // 自适应坐标轴范围

    // 连接将某些轴选择连接在一起的插槽(特别是相对的轴):
    connect(customPlot, SIGNAL(selectionChangedByUser()), this, SLOT(selectionChanged())); // 选择时调用
    // 连接插槽时,请注意在选择轴时,只能拖动和缩放该方向:
    connect(customPlot, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(mousePress())); // 缩放时调用
    connect(customPlot, SIGNAL(mouseWheel(QWheelEvent*)), this, SLOT(mouseWheel())); // 拖动时调用

    // 使底部和左侧轴将其范围转移到顶部和右侧轴:
    connect(customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->xAxis2, SLOT(setRange(QCPRange))); // 同步显示范围
    connect(customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->yAxis2, SLOT(setRange(QCPRange)));

    //连接一些交互插槽:
    connect(customPlot, SIGNAL(axisDoubleClick(QCPAxis*,QCPAxis::SelectablePart,QMouseEvent*)), this, SLOT(axisLabelDoubleClick(QCPAxis*,QCPAxis::SelectablePart))); // 双击时修改
    connect(customPlot, SIGNAL(legendDoubleClick(QCPLegend*,QCPAbstractLegendItem*,QMouseEvent*)), this, SLOT(legendDoubleClick(QCPLegend*,QCPAbstractLegendItem*)));
    connect(title, SIGNAL(doubleClicked(QMouseEvent*)), this, SLOT(titleDoubleClick(QMouseEvent*)));

    //当单击图形时,连接插槽会在状态栏中显示一条消息:
    connect(customPlot, SIGNAL(plottableClick(QCPAbstractPlottable*,int,QMouseEvent*)), this, SLOT(graphClicked(QCPAbstractPlottable*,int)));

    //为上下文菜单弹出设置策略和连接槽:
    customPlot->setContextMenuPolicy(Qt::CustomContextMenu); // 小部件如何显示上下文菜单
    connect(customPlot, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequest(QPoint)));
}
  • 初始化内容, 设置初始的允许操作,设置初始化的图例, 添加初始化的曲线,连接交互用的槽函数;
  • 注意拖动和缩放的交互是如何实现的.

14.总结

  • 至此已经能实现一些基本的交互和操作, 接下来就是显示游标和文字.

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

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

相关文章

openMetaData docker方式安装部署记录

OpenMetadata一站式元数据管理平台&#xff0c;是一款功能强大的开源元数据管理平台&#xff0c;旨在帮助企业更好地发现、理解和管理其数据资产。它提供了一套全面的工具和功能&#xff0c;涵盖了数据发现、数据血缘、数据质量、数据探查、数据治理和团队协作等多个方面。 那…

57. Three.js案例-创建一个带有聚光灯和旋转立方体的3D场景

57. Three.js案例-创建一个带有聚光灯和旋转立方体的3D场景 实现效果 该案例实现了使用Three.js创建一个带有聚光灯和旋转立方体的3D场景。 知识点 WebGLRenderer&#xff08;WebGL渲染器&#xff09; THREE.WebGLRenderer 是 Three.js 中用于将场景渲染为 WebGL 内容的核…

本地视频进度加入笔记+根据进度快速锁定视频位置

本地视频进度记录快速回溯 引言 在学习的过程中, 如果我们想快速记录当前看视频的位置, 后续回溯查找就会非常方便了。 实现效果 进度记录 通过按下快捷键ctrlaltu&#xff0c; 快速记录当前视频的进度信息,然后复制到typora软件内 快速回溯 在typora软件内, 选中视频索引…

Spring Boot 支持哪些日志框架

Spring Boot 支持多种日志框架&#xff0c;主要包括以下几种&#xff1a; SLF4J (Simple Logging Facade for Java) Logback&#xff08;默认&#xff09;Log4j 2Java Util Logging (JUL) 其中&#xff0c;Spring Boot 默认使用 SLF4J 和 Logback 作为日志框架。如果你需要使…

快速导入请求到postman

1.确定请求&#xff0c;右键复制为cURL(bash) 2.postman菜单栏Import-Raw text&#xff0c;粘贴复制的内容保存&#xff0c;请求添加成功

Golang的网络流量分配策略

## 1. Golang中的网络流量分配策略 简介 在Golang中&#xff0c;网络流量分配策略是指如何有效地管理和优化网络请求的分配&#xff0c;以提高系统的性能和稳定性。优秀的网络流量分配策略能够使系统更好地应对高并发和大流量的情况&#xff0c;同时有效地避免网络拥堵和性能瓶…

【硬件介绍】Type-C接口详解

一、Type-C接口概述 Type-C接口特点&#xff1a;以其独特的扁头设计和无需区分正反两面的便捷性而广受欢迎。这种设计大大提高了用户的使用体验&#xff0c;避免了传统USB接口需要多次尝试才能正确插入的问题。Type-C接口内部结构&#xff1a;内部上下两排引脚的设计虽然可能不…

二、BIO、NIO编程与直接内存、零拷贝

一、网络通信 1、什么是socket&#xff1f; Socket 是应用层与 TCP/IP 协议族通信的中间软件抽象层&#xff0c;它是一组接口&#xff0c;一般由操作 系统提供。客户端连接上一个服务端&#xff0c;就会在客户端中产生一个 socket 接口实例&#xff0c;服务端每接受 一个客户端…

Android车机DIY开发之软件篇(九)默认应用和服务修改

Android车机DIY开发之软件篇(九)默认应用和服务修改 默认应用位置 ~/packages/apps/Car 增加APP 1.增加 XXXX.app 和Android.mk 2. 修改~/build/make/target/product/handheld_system_ext.mk 默认服务位置 ~/frameworks/base/services/java/com/android/server 查看服务列…

【Rust】错误处理机制

目录 思维导图 引言 一、错误处理的重要性 1.1 软件中的错误普遍存在 1.2 编译时错误处理要求 二、错误的分类 2.1 可恢复错误&#xff08;Recoverable Errors&#xff09; 2.2 不可恢复错误&#xff08;Unrecoverable Errors&#xff09; 三、Rust 的错误处理机制 3…

DDD - 微服务设计与领域驱动设计实战(上)_统一建模语言及事件风暴会议

文章目录 Pre概述业务流程需求分析的困境统一语言建模事件风暴会议什么是事件风暴&#xff08;Event Storming&#xff09;事件风暴会议 总结 Pre DDD - 软件退化原因及案例分析 DDD - 如何运用 DDD 进行软件设计 DDD - 如何运用 DDD 进行数据库设计 DDD - 服务、实体与值对…

用HTML + CSS实现太极图

目录 一、效果图 二、实现思路 三、完整代码 四、总结 一、效果图 如图所示&#xff0c;太极图一半为黑色&#xff08;代表阴&#xff09;&#xff0c;另一半为白色&#xff08;代表阳&#xff09;。这两部分相互环绕&#xff0c;形成一种流动的、旋转的感觉。 二、实现思…

Apache Hadoop YARN框架概述

一、YARN产生和发展简史 1.1背景 数据、程序、运算资源&#xff08;内存、CPU&#xff09;三者组在一起&#xff0c;才能完成数据的计算处理过程。在单机环境下&#xff0c;三者之间协调配合不是太大问题。为了应对海量数据的处理场景&#xff0c;Hadoop软件出现并提供了分布…

一个个顺序挨着来 - 责任链模式(Chain of Responsibility Pattern)

责任链模式&#xff08;Chain of Responsibility Pattern&#xff09; 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;概述责任链结构图责任链模式概述责任链模式涉及的角色 talk is c…

.NET framework、Core和Standard都是什么?

对于这些概念一直没有深入去理解&#xff0c;以至于经过.net这几年的发展进化&#xff0c;概念越来越多&#xff0c;越来越梳理不容易理解了。内心深处存在思想上的懒惰&#xff0c;以为自己专注于Unity开发就好&#xff0c;这些并不属于核心范畴&#xff0c;所以对这些概念总是…

【Java回顾】Day5 并发基础|并发关键字|JUC全局观|JUC原子类

JUC全称java.util.concurrent 处理并发的工具包(线程管理、同步、协调) 一.并发基础 多线程要解决什么问题&#xff1f;本质是什么&#xff1f; CPU、内存、I/O的速度是有极大差异的&#xff0c;为了合理利用CPU的高性能&#xff0c;平衡三者的速度差异&#xff0c;解决办法…

android framework.jar 在应用中使用

在开发APP中&#xff0c;有时会使用系统提供的framework.jar 来替代 android.jar, 在gradle中配置如下&#xff1a; 放置framework.jar 依赖配置 3 优先级配置 gradle.projectsEvaluated {tasks.withType(JavaCompile) {Set<File> fileSet options.bootstrapClasspat…

CHAIN OF RESPONSIBILITY(职责链)—对象行为型模式

1. 意图 使多个对象都有机会处理请求&#xff0c;从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链&#xff0c;并沿着这条链传递该请求&#xff0c;直到有一个对象处理它为止。 2. 动机 考虑一个图形用户界面中的上下文有关的帮助机制。用户在界面的任一部分…

Java高频面试之SE-11

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本牛马baby今天又来了&#xff01;哈哈哈哈哈嗝&#x1f436; Java中是引用传递还是值传递&#xff1f; 在 Java 中&#xff0c;方法参数传递是通过 值传递 的方式实现的&#xff0c;但这可能会引起一…

VsCode对Arduino的开发配置

ps&#xff1a;我的情况是在对esp32进行编译、烧录时&#xff0c;找不到按钮&#xff0c;无法识别Arduino文件&#xff0c;适合已经有ini文件的情况。 1.在vscode中安装拓展 2.打开设置&#xff0c;点击右上角&#xff0c;转到settings.json文件 3.复制以下代码并保存 {"…