爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      QCustomPlot开发笔记(二):QCustomPlot用户交互、元素项以及特殊用法

      首页 知识中心 软件开发 文章详情页

      QCustomPlot开发笔记(二):QCustomPlot用户交互、元素项以及特殊用法

      2024-09-25 10:15:15 阅读次数:221

      编程开发

      前言

        上一篇讲解了,基础绘图,本片继续描述用户交互、元素项以及Qt中的一些特殊用法。

      QCustomPlot用户交互

        QCustomPlot 提供多种内置的用户交互。它们大致可以分为:

      • 通过鼠标拖动和滚动鼠标滚轮进行范围操作
      • 通过单击选择绘图实体
      • 用户点击绘图实体时发出的信号

      范围操作

      拽托

        用户操作轴范围的默认方法是在相应的QCPAxisRect上执行拖动操作。   QCustomPlot开发笔记(二):QCustomPlot用户交互、元素项以及特殊用法   要在QCustomPlot小部件中启用范围拖动,需要将标志QCP::iRangeDrag添加到当前允许的交互中。这可以通过customPlot->setInteraction(QCP::iRangeDrag, true)完成。要仅允许在一个方向上拖动,使用QCPAxisRect::setRangeDrag并指定Qt::Vertical或Qt::Horizontal。默认为两个方向都允许Qt::Vertical | Qt::Horizontal。   在拖动操作过程中,通过QCPAxisRect::setRangeDragAxes配置的轴会实时更新其范围,从而自动调用replots。这会给用户一种用鼠标抓取绘图坐标平面的印象。最初,范围拖动轴配置为矩形的底部和左侧轴。   在拖动操作期间,通过实时更新其范围配置的轴,自动导致重新绘制。这给用户一种通过用鼠标抓住绘图坐标平面来移动它的印象。最初,范围拖动轴被配置为矩形的底部和左侧轴。对于QCustomPlot小部件的默认为横轴和纵轴,它们是QCustomPlot::xAxis和QCustomPlot::yAxis。

      缩放

        要更改范围的大小,即放大或缩小绘图,用户可以使用鼠标滚轮。此行为由交互标志QCP::iRangeZoom控制,该标志还需要通过QCustomPlot::setInteraction激活。与范围拖动一样,缩放也可能会针对受影响的轴和方向进行选择,请参见函数QCPAxisRect::setRangeZoomAxes和QCPAxisRect::setRangeZoom。   此外,可以使用QCPAxisRect::setRangeZoomFactor控制缩放因子。在普通鼠标硬件上,一个鼠标滚轮步长对应于应用于轴范围的该因子。如果系数大于1,则向前滚动鼠标滚轮会减小范围(放大),向后滚动则会增大范围(缩小)。要反转此行为,请将鼠标滚轮缩放因子设置为小于1(但大于零)。缩放始终以绘图中的当前鼠标光标位置为中心。这意味着将光标指向感兴趣的功能,滚动鼠标滚轮可以放大该功能。

      选择机制

        QCustomPlot开发笔记(二):QCustomPlot用户交互、元素项以及特殊用法   QCustomPlot提供了一种选择机制,允许用户潜在地选择绘图中的每个组件,如轴和图形。可以使用以QCP::iSelect(…) 开头的交互标志来控制特定类别的实体在绘图中是否通常是可选择的。例如,设置customPlot->setInteraction(QCP::iSelectPlottables, true) 将允许用户通过单击来选择绘图表(例如图形)。查看QCP::Interaction文档中的所有交互标志。要允许同时选择多个对象,请设置QCP::iMultiSelect交互标志。然后,用户可以通过按住“多重选择”修改器(请参见QCustomPlot::setMultiSelectModifier)连续选择多个对象,默认情况下,该修改器为Ctrl。

      控制个体的可选择性和选择状态

        通过在单个对象上使用setSelectable函数,可以进一步微调可选择性。例如,如果用户无法选择绘图中的特定图形,请调用thatGraph->setSelectable(false)。可以通过setSelected函数以编程方式修改选定状态。即使用户的可选择性被禁用,也可以通过编程更改选择状态。   要取消选择绘图中的所有对象,请调用QCustomPlot::deselectAll。

      选定对象的外观

        选定的对象通常使用不同的笔、画笔或字体显示。可以使用QCPGraph::setSelectedPen、QCPGraph::setSelectedBrush、QCPAxis::setSelectedLabelFont、QCPAxis::setSelectedBasePen、QCPItemText::setSelectedColor等方法进行配置。可以看出,它们的命名与原始(非选定)属性类似,但前缀为“选定”。

      多部分对象

        某些对象(如轴和图例)的外观更为复杂,因此仅选择一个布尔值是不够的。在这些情况下,selectability和selection state都是SelectablePart标志的or组合(相应的QFlags类型称为SelectableParts)。每个多部件对象定义自己的SelectablePart类型。   QCustomPlot开发笔记(二):QCustomPlot用户交互、元素项以及特殊用法   例如,QCPAxis在概念上由三部分组成:带有记号的轴主干、记号标签(数字)和轴标签。由于这三个部分可以单独选择,QCPAxis::SelectablePart定义了QCPAxis::spNone、QCPAxis: :spAxis、QCPAxis::spTickLabels和QCPAxis::spAxisLabel。要使轴主干和刻度标签可选择,但不能选择轴标签,则可调用theAxis->SetSelectableParts(QCPAxis::spAxis | QCP::spTickLabels)。要控制多部分对象的当前选择状态,请使用QCPAxis::setSelectedParts方法。

      对选择变化做出反应

        在选择更改后,每个对象都会发出一个名为selectionChanged的信号。无论更改是由用户引起的,还是通过调用setSelected/setSelectedParts以编程方式引起的,都无关紧要。   如果用户交互改变了绘图中的选择,则会发出QCustomPlot宽信号QCustomPlot::selectionChangedByUser。在与此信号相连的插槽中,可以检查某些对象的选择状态,并做出相应的反应。QCustomPlot::selectedPlottables、selectedItems、selectedAxes和selectedLegends方法在这里可能有助于检索特定类型的选定对象。

      用户交互信号

        QCustomPlot独立于选择机制,在用户交互时发出各种信号。最低级的是QCustomPlot::mouseDoubleClick、mousePress、mouseMove、mouseRelease和mouseWheel信号。当QCustomPlot小部件的相应事件触发时,它们就会发出。请注意,最干净的方法是将QCustomPlot子类化,并用相同的名称重新实现事件方法(从QWidget继承)。然而,如果不想将QCustomPlot子类化,这些信号允许更容易地访问简单任务的用户交互。   还有更高级别的信号报告绘图中某些对象的单击和双击:QCustomPlot::plottableClick、plottableDoubleClick、itemClick、itemDoubleClick、axisClick、axisDoubleClick、legendClick、legendDoubleClick、titleClick和titleDoubleClick。所有这些信号都会报告单击了哪个对象(如果是多部分对象,则报告单击了哪个部分),以及相关的QMouseEvent。

      元素项:支持的图形元素

        QCustomPlot允许在绘图上放置和锚定图形元素,如文本、箭头、线、矩形、任意像素地图等。它们基于抽象基类QCPAbstractItem。QCPAbstractItem的文档中详细描述了项机制以及当前可用的内置项。

      使用箭头和文本的基本示例

        此示例显示如何创建始终位于轴矩形顶部的文本标签,以及将打印坐标中的点与该标签连接的箭头。

      // add the text label at the top:
      QCPItemText *textLabel = new QCPItemText(customPlot);
      textLabel->setPositionAlignment(Qt::AlignTop|Qt::AlignHCenter);
      textLabel->position->setType(QCPItemPosition::ptAxisRectRatio);
      textLabel->position->setCoords(0.5, 0); // place position at center/top of axis rect
      textLabel->setText("Text Item Demo");
      textLabel->setFont(QFont(font().family(), 16)); // make font a bit larger
      textLabel->setPen(QPen(Qt::black)); // show black border around text
       
      // add the arrow:
      QCPItemLine *arrow = new QCPItemLine(customPlot);
      arrow->start->setParentAnchor(textLabel->bottom);
      arrow->end->setCoords(4, 1.6); // point to (4, 1.6) in x-y-plot coordinates
      arrow->setHead(QCPLineEnding::esSpikeArrow);
      

        请注意,即使拖动打印范围,箭头仍会附着在打印坐标(4,1.6)上,并相应地旋转/拉伸。这是通过QCustomPlot项目定位的灵活性实现的。项目可以在打印坐标、绝对像素坐标和轴矩形大小的分数单位中定位。QCPAbstractItem和QCPItemPosition的文档更详细地介绍了如何使用这些不同的可能性。   QCustomPlot开发笔记(二):QCustomPlot用户交互、元素项以及特殊用法   与绘图表一样,创建自己的项目也很容易。这可以通过创建自己的QCPAbstractItem子类来实现。请参阅QCPAbstractItem文档中的子类部分。

      项剪切

        默认情况下,项目被剪裁到主轴矩形,这意味着它们仅在主轴矩形内可见。要使项目在该axis rect外部可见,请通过调用setClipToAxisRect(false) 禁用剪裁。   另一方面,如果希望将项目剪裁到不同的轴rect,可以通过setClipAxisRect指定它。项目的clipAxisRect属性仅用于剪裁行为,原则上与项目可能通过其位置成员绑定到的坐标轴无关(请参见QCPItemPosition::SetAxis)。但是,通常情况下,用于剪裁的轴rect也包含用于项目位置的轴。

      更高级的使用

        有关QCustomPlot的项目系统可以实现的更高级、更真实的演示,请查看“特殊用例”教程“项目动态轴标记”。

      特殊用法

        在QTextDocument中嵌入绘图生成报告通常需要在文本文档中插入绘图和图表。   示例演示了QCustomPlot如何与QTextDocument交互,以轻松实现这一点。   示例项目是完整下载包的一部分。   QCustomPlot开发笔记(二):QCustomPlot用户交互、元素项以及特殊用法

      QCPDocumentObject

        QCustomPlot和QTextDocument之间的接口是QCPDocumentObject。请注意,此类不在标准qcustomplot中。cpp/。h文件,但在qcpdocumentobject中定义。cpp/。h在本教程的示例项目中。   它有两个目的:

      • 从QCustomPlot生成文本字符格式。这允许在QTextDocument中插入绘图,例如在光标位置。
      • 重新绘制或导出QTextDocument时,在QTextDocument内呈现静态绘图。   文本字符格式有什么好处:使用自定义格式插入QChar::ObjectReplacementCharacter是Qt允许将自定义对象插入文本文档的方式。   假设QCustomPlot是ui->plot,而文本文档的QTextEdit是ui->textEdit。第一步是将QCPDocumentObject注册为文本文档中打印对象的处理程序:
      // register the plot document object (only needed once, no matter how many plots will be in the QTextDocument):
      QCPDocumentObject *plotObjectHandler = new QCPDocumentObject(this);
      ui->textEdit->document()->documentLayout()->registerHandler(QCPDocumentObject::PlotTextFormat, plotObjectHandler);
      

        在这个调用之后,我们可以开始在文本文档中插入绘图。这就是静态方法QCPDocumentObject::generatePlotFormat(QCustomPlot *plot, int width, int height)的优点。它以给定的宽度和高度(如果保留为0,则使用绘图的当前宽度和高度)获取绘图的矢量化快照,并将其附加到QTextCharFormat。返回的QTextCharFormat随后可用于格式化QChar::ObjectReplacementCharacter,该字符随后显示为绘图对象。因此,可以按如下方式在当前光标位置插入绘图:

      QTextCursor cursor = ui->textEdit->textCursor();
       
      // insert the current plot at the cursor position. QCPDocumentObject::generatePlotFormat creates a
      // vectorized snapshot of the passed plot (with the specified width and height) which gets inserted
      // into the text document.
      double width = ui->cbUseCurrentSize->isChecked() ? 0 : ui->sbWidth->value();
      double height = ui->cbUseCurrentSize->isChecked() ? 0 : ui->sbHeight->value();
      cursor.insertText(QString(QChar::ObjectReplacementCharacter), QCPDocumentObject::generatePlotFormat(ui->plot, width, height));
       
      ui->textEdit->setTextCursor(cursor);
      

        组件cbUseCurrentSize、sbWidth和sbHeight是示例项目用户界面的一部分。如上所述,文本文档中的plot对象保持其矢量化性质。因此,将其导出为PDF(或其他能够矢量化内容的格式)可以获得最高质量的输出。将上述文档保存为PDF文件,并在PDF查看器中打开,将显示以下内容   QCustomPlot开发笔记(二):QCustomPlot用户交互、元素项以及特殊用法   可以看出,放大插入的绘图可以显示平滑的线条。

      用滚动条控制轴范围

        虽然控制轴范围最直观的方法是范围拖动和缩放机制,但也可能需要为此提供滚动条。这可以通过信号和插槽将轴与滚动条连接来实现。在轴的QCPRange和滚动条的整数值之间转换需要一个中间槽。   示例项目名为scrollbar axis range control,是完整下载包的一部分。   QCustomPlot开发笔记(二):QCustomPlot用户交互、元素项以及特殊用法

      预设限制

        与在滚动条和轴之间来回传播更改相关的信号是QScrollBar::valueChanged(int)和QCPAxis::rangeChanged(QCPRange)。由于我们希望保持正常范围的拖动和缩放,当轴的rangeChanged信号发出时,滚动条滑块的位置和大小必须更新。   QScrollBar是基于整数的。因此,我们需要一个将整数滚动条值转换为轴坐标的因子。例如,如果希望能够在坐标范围-5到5之间平滑地滚动轴,我们可以将因子设置为0.01(即将滚动条值除以100),从而将滚动条的范围设置为-500,500。

      ui->horizontalScrollBar->setRange(-500, 500);
      ui->verticalScrollBar->setRange(-500, 500);
      

        如果可访问的坐标范围在任何点发生变化,只需更改滚动条的最大值/最小值即可。 进行坐标变换的中间槽称为horzScrollBarChanged、vertScrollBarChanged、xAxisChanged和yAxisChanged。它们连接到滚动条和x-/y轴的相应信号:

      connect(ui->horizontalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(horzScrollBarChanged(int)));
      connect(ui->verticalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(vertScrollBarChanged(int)));
      connect(ui->plot->xAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(xAxisChanged(QCPRange)));
      connect(ui->plot->yAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(yAxisChanged(QCPRange)));
      

      坐标变换槽

        这两种类型的插槽(轴范围到滚动条和滚动条到轴范围)都相当简单。它们分别获取滚动条或滚动条的更改值,应用转换并将结果设置为轴或滚动条。这些插槽用于在移动滚动条滑块时更新轴范围:

      void MainWindow::horzScrollBarChanged(int value)
      {
        // if user is dragging plot, we don't want to replot twice
        if (qAbs(ui->plot->xAxis->range().center()-value/100.0) > 0.01) 
        {
          ui->plot->xAxis->setRange(value/100.0, ui->plot->xAxis->range().size(), Qt::AlignCenter);
          ui->plot->replot();
        }
      }
       
      void MainWindow::vertScrollBarChanged(int value)
      {
        // if user is dragging plot, we don't want to replot twice
        if (qAbs(ui->plot->yAxis->range().center()+value/100.0) > 0.01) 
        {
          ui->plot->yAxis->setRange(-value/100.0, ui->plot->yAxis->range().size(), Qt::AlignCenter);
          ui->plot->replot();
        }
      }
      

        首先,我们在这里看到滚动条值除以100.0到轴坐标的转换。还请注意:

      • 当滑块位于顶部时,垂直滚动条的值较低;
      • 当滑块位于底部时,垂直滚动条的值较高。

        对于打印轴,情况正好相反,这就是为什么在包含垂直滚动条值的表达式中添加减号的原因,例如在设置yAxis范围时。   条件qAbs(ui->plot->xAxis->range().center()-value/100.0)>0.01是必要的,这样范围拖动不会导致双重触发,这是由更改信号和插槽之间的来回切换引起的。这可能是因为在范围拖动时,QCustomPlot会自动重新打印自己,并发出被拖动轴的范围更改信号。在这个应用程序中,rangeChanged信号将调用插槽xAxisChanged或yAxisChanged,它通过调用滚动条的setValue方法来更新滚动条滑块的位置。此方法依次发出滚动条的valueChanged信号,该信号连接到上面的插槽。在这里,如果值变化,第二次变化就会发生。该检查确保仅当当前轴范围与新的(转换的)滚动条值实际不同时才执行replot。如果用户拖动轴范围,则不会出现这种情况,因此会跳过冗余的replot和轴范围更新。   轴范围更改时更新滚动条的插槽很简单:

      void MainWindow::xAxisChanged(QCPRange range)
      {
        // adjust position of scroll bar slider
        ui->horizontalScrollBar->setValue(qRound(range.center()*100.0)); 
        // adjust size of scroll bar slider
        ui->horizontalScrollBar->setPageStep(qRound(range.size()*100.0)); 
      }
      
      void MainWindow::yAxisChanged(QCPRange range)
      {
        // adjust position of scroll bar slider
        ui->verticalScrollBar->setValue(qRound(-range.center()*100.0)); 
        // adjust size of scroll bar slider
        ui->verticalScrollBar->setPageStep(qRound(range.size()*100.0)); 
      }
      

      使用项目创建动态轴标记

        这个例子演示了QCustomPlot的item系统的更高级的用法。创建了一个新的小类AxisTag,它管理一组项目,这些项目一起构成指向轴并高亮显示特定坐标的标记。   为了在主应用程序中展示它,在axis rect的右侧创建了两个轴,并制作了两个相应的标记,以指示连续更新的两个图形的最右侧数据点值。   示例项目称为axis tags example,是完整下载包的一部分:   QCustomPlot开发笔记(二):QCustomPlot用户交互、元素项以及特殊用法

      处理相关项目的新类

        在上面的屏幕截图中看到的标记由两个可见项组成:一个QCPItemText,它以矩形边框包围的文本形式为我们提供当前坐标;另一个QCPItemLine,其头部的线条端点设置为箭头形状,提供指向左侧的箭头。   然而,还有另一个不可见的项目可以帮助定位标签。QCPItemTracer位于右轴矩形边界(内轴的水平位置)的相应值坐标高度处。它为其他项提供主父锚点,因此上下移动跟踪器将上下移动整个标记。   在主窗口代码中分别管理这三个项目很容易出错,而且风格也不好。因此,创建了一个新的类AxisTag,负责设置和处理这三个项。以下是AxisTag类的头代码:

      #include <QObject>
      #include "qcustomplot.h"
       
      class AxisTag : public QObject
      {
        Q_OBJECT
      public:
        explicit AxisTag(QCPAxis *parentAxis);
        virtual ~AxisTag();
         
        // setters:
        void setPen(const QPen &pen);
        void setBrush(const QBrush &brush);
        void setText(const QString &text);
         
        // getters:
        QPen pen() const { return mLabel->pen(); }
        QBrush brush() const { return mLabel->brush(); }
        QString text() const { return mLabel->text(); }
         
        // other methods:
        void updatePosition(double value);
         
      protected:
        QCPAxis *mAxis;
        QPointer<QCPItemTracer> mDummyTracer;
        QPointer<QCPItemLine> mArrow;
        QPointer<QCPItemText> mLabel;
      };
      

        为了本示例的清晰性,将接口保持在最小值。在现实世界中,用户可能需要该类的更多定制和额外功能,例如,一个泛化来支持其他轴方向。   下一个代码段是AxisTag类的实现。在其构造函数中,三个项之间建立了以下锚定父子关系。青蓝色圆圈表示QCPItemTracer位置、QCPItemLine结束/开始位置和QCPItemText位置。   QCustomPlot开发笔记(二):QCustomPlot用户交互、元素项以及特殊用法   可以找到相关代码段的解释:

      #include "axistag.h"
       
      AxisTag::AxisTag(QCPAxis *parentAxis) :
        QObject(parentAxis),
        mAxis(parentAxis)
      {
        // The dummy tracer serves here as an invisible anchor which always sticks to the right side of
        // the axis rect
        mDummyTracer = new QCPItemTracer(mAxis->parentPlot());
        mDummyTracer->setVisible(false);
        mDummyTracer->position->setTypeX(QCPItemPosition::ptAxisRectRatio);
        mDummyTracer->position->setTypeY(QCPItemPosition::ptPlotCoords);
        mDummyTracer->position->setAxisRect(mAxis->axisRect());
        mDummyTracer->position->setAxes(0, mAxis);
        mDummyTracer->position->setCoords(1, 0);
         
        // the arrow end (head) is set to move along with the dummy tracer by setting it as its parent
        // anchor. Its coordinate system (setCoords) is thus pixels, and this is how the needed horizontal
        // offset for the tag of the second y axis is achieved. This horizontal offset gets dynamically
        // updated in AxisTag::updatePosition. the arrow "start" is simply set to have the "end" as parent
        // anchor. It is given a horizontal offset to the right, which results in a 15 pixel long arrow.
        mArrow = new QCPItemLine(mAxis->parentPlot());
        mArrow->setLayer("overlay");
        mArrow->setClipToAxisRect(false);
        mArrow->setHead(QCPLineEnding::esSpikeArrow);
        mArrow->end->setParentAnchor(mDummyTracer->position);
        mArrow->start->setParentAnchor(mArrow->end);
        mArrow->start->setCoords(15, 0);
         
        // The text label is anchored at the arrow start (tail) and has its "position" aligned at the
        // left, and vertically centered to the text label box.
        mLabel = new QCPItemText(mAxis->parentPlot());
        mLabel->setLayer("overlay");
        mLabel->setClipToAxisRect(false);
        mLabel->setPadding(QMargins(3, 0, 3, 0));
        mLabel->setBrush(QBrush(Qt::white));
        mLabel->setPen(QPen(Qt::blue));
        mLabel->setPositionAlignment(Qt::AlignLeft|Qt::AlignVCenter);
        mLabel->position->setParentAnchor(mArrow->start);
      }
       
      AxisTag::~AxisTag()
      {
        if (mDummyTracer)
          mDummyTracer->parentPlot()->removeItem(mDummyTracer);
        if (mArrow)
          mArrow->parentPlot()->removeItem(mArrow);
        if (mLabel)
          mLabel->parentPlot()->removeItem(mLabel);
      }
       
      void AxisTag::setPen(const QPen &pen)
      {
        mArrow->setPen(pen);
        mLabel->setPen(pen);
      }
       
      void AxisTag::setBrush(const QBrush &brush)
      {
        mLabel->setBrush(brush);
      }
       
      void AxisTag::setText(const QString &text)
      {
        mLabel->setText(text);
      }
       
      void AxisTag::updatePosition(double value)
      {
        // since both the arrow and the text label are chained to the dummy tracer (via anchor
        // parent-child relationships) it is sufficient to update the dummy tracer coordinates. The
        // Horizontal coordinate type was set to ptAxisRectRatio so to keep it aligned at the right side
        // of the axis rect, it is always kept at 1. The vertical coordinate type was set to
        // ptPlotCoordinates of the passed parent axis, so the vertical coordinate is set to the new
        // value.
        mDummyTracer->position->setCoords(1, value);
         
        // We want the arrow head to be at the same horizontal position as the axis backbone, even if
        // the axis has a certain offset from the axis rect border (like the added second y axis). Thus we
        // set the horizontal pixel position of the arrow end (head) to the axis offset (the pixel
        // distance to the axis rect border). This works because the parent anchor of the arrow end is
        // the dummy tracer, which, as described earlier, is tied to the right axis rect border.
        mArrow->end->setCoords(mAxis->offset(), 0);
      }
      

      主要应用

        主应用程序现在使用了这个新的AxisTag类,从而避免了直接进行项操作,所有这些都是在AxisTag实例中处理的。   这是MainWindow类的标题。与之前一样,可以在内联注释中找到解释:

      #include <QMainWindow>
      #include "qcustomplot.h"
      #include "axistag.h"
       
      namespace Ui {
      class MainWindow;
      }
       
      class MainWindow : public QMainWindow
      {
        Q_OBJECT
         
      public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
         
      private slots:
        void timerSlot();
         
      private:
        Ui::MainWindow *ui;
        QCustomPlot *mPlot;
        QPointer<QCPGraph> mGraph1;
        QPointer<QCPGraph> mGraph2;
        AxisTag *mTag1;
        AxisTag *mTag2;
        QTimer mDataTimer;
      };
      

        最后是MainWindow类的实现。它基本上在右边设置了两个y轴、两个图形和两个轴标记。timerSlot()由QTimer重复调用。在插槽中,新的数据点被添加到图形中,标记通过AxisTag::updatePosition方法更新。

      #include "mainwindow.h"
      #include "ui_mainwindow.h"
       
      MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow),
        mPlot(0),
        mTag1(0),
        mTag2(0)
      {
        ui->setupUi(this);
         
        mPlot = new QCustomPlot(this);
        setCentralWidget(mPlot);
         
        // configure plot to have two right axes:
        mPlot->yAxis->setTickLabels(false);
        connect(mPlot->yAxis2, SIGNAL(rangeChanged(QCPRange)), mPlot->yAxis, SLOT(setRange(QCPRange))); // left axis only mirrors inner right axis
        mPlot->yAxis2->setVisible(true);
        mPlot->axisRect()->addAxis(QCPAxis::atRight);
        mPlot->axisRect()->axis(QCPAxis::atRight, 0)->setPadding(30); // add some padding to have space for tags
        mPlot->axisRect()->axis(QCPAxis::atRight, 1)->setPadding(30); // add some padding to have space for tags
         
        // create graphs:
        mGraph1 = mPlot->addGraph(mPlot->xAxis, mPlot->axisRect()->axis(QCPAxis::atRight, 0));
        mGraph2 = mPlot->addGraph(mPlot->xAxis, mPlot->axisRect()->axis(QCPAxis::atRight, 1));
        mGraph1->setPen(QPen(QColor(250, 120, 0)));
        mGraph2->setPen(QPen(QColor(0, 180, 60)));
         
        // create tags with newly introduced AxisTag class (see axistag.h/.cpp):
        mTag1 = new AxisTag(mGraph1->valueAxis());
        mTag1->setPen(mGraph1->pen());
        mTag2 = new AxisTag(mGraph2->valueAxis());
        mTag2->setPen(mGraph2->pen());
         
        connect(&mDataTimer, SIGNAL(timeout()), this, SLOT(timerSlot()));
        mDataTimer.start(40);
      }
       
      MainWindow::~MainWindow()
      {
        delete ui;
      }
       
      void MainWindow::timerSlot()
      {
        // calculate and add a new data point to each graph:
        mGraph1->addData(mGraph1->dataCount(), qSin(mGraph1->dataCount()/50.0)+qSin(mGraph1->dataCount()/50.0/0.3843)*0.25);
        mGraph2->addData(mGraph2->dataCount(), qCos(mGraph2->dataCount()/50.0)+qSin(mGraph2->dataCount()/50.0/0.4364)*0.15);
       
        // make key axis range scroll with the data:
        mPlot->xAxis->rescale();
        mGraph1->rescaleValueAxis(false, true);
        mGraph2->rescaleValueAxis(false, true);
        mPlot->xAxis->setRange(mPlot->xAxis->range().upper, 100, Qt::AlignRight);
         
        // update the vertical axis tag positions and texts to match the rightmost data point of the graphs:
        double graph1Value = mGraph1->dataMainValue(mGraph1->dataCount()-1);
        double graph2Value = mGraph2->dataMainValue(mGraph2->dataCount()-1);
        mTag1->updatePosition(graph1Value);
        mTag2->updatePosition(graph2Value);
        mTag1->setText(QString::number(graph1Value, 'f', 2));
        mTag2->setText(QString::number(graph2Value, 'f', 2));ss
         
        mPlot->replot();
      }
      
      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.51cto.com/hongpangzi/5273015,作者:长沙红胖子Qt,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:Python为数据添加拉普拉斯噪声Laplace noise

      下一篇:快速入门 - Spring Boot 集成 Redis 配置及使用

      相关文章

      2024-11-06 07:24:46

      图的存储

      图的存储 

      2024-11-06 07:24:46
      存储 , 编程开发
      2024-09-25 10:15:32

      几种距离度量

      几种距离度量

      2024-09-25 10:15:32
      python , 编程开发
      2024-09-25 10:15:32

      Python实战技巧(9)Python发送邮件

      Python实战技巧(9)Python发送邮件

      2024-09-25 10:15:32
      python , 编程开发
      2024-09-25 10:15:32

      R语言文本挖掘tf-idf,主题建模,情感分析,n-gram建模研究|附代码数据

      R语言文本挖掘tf-idf,主题建模,情感分析,n-gram建模研究|附代码数据

      2024-09-25 10:15:32
      R语言开发 , 编程开发
      2024-09-25 10:15:32

      SpringCloud-技术专区-Gateway基于OAuth2.0 的身份认证

      Spring Cloud Gateway 可以通过代码或者配置文件指定路由,我还是习惯在配置文件里面操作。这里简单配置将所有 /api/** 的请求都转发到 api-service 进行处理。

      2024-09-25 10:15:32
      Spring , 编程开发
      2024-09-25 10:15:32

      Python使用神经网络进行简单文本分类

      Python使用神经网络进行简单文本分类

      2024-09-25 10:15:32
      python , 编程开发
      2024-09-25 10:15:32

      Python3 - 时间处理与定时任务

      无论哪种编程语言,时间肯定都是非常重要的部分,今天来看一下python如何来处理时间和python定时任务,注意咯:本篇所讲是python3版本的实现,在python2版本中的实现略有不同,有时间会再写一篇以便大家区分。

      2024-09-25 10:15:32
      python , 编程开发
      2024-09-25 10:15:15

      用Devc++与easyx一步一步做游戏[启动界面部分]-之按钮制作

      GIF截图看不到鼠标移动的效果,实际上这里是随着鼠标的移动而显示的效果,鼠标移动到对应的菜单上则下面的提示文字显示对应的内容,离开按钮则恢复显示CopyRight的信息。

      2024-09-25 10:15:15
      c++ , 算法 , 编程开发
      2024-09-25 10:15:01

      Python为数据添加拉普拉斯噪声Laplace noise

      Python为数据添加拉普拉斯噪声Laplace noise

      2024-09-25 10:15:01
      python , 编程开发
      2024-09-25 10:15:01

      python - 绘制与数据相关的标记和颜色的3D散点图

      python - 绘制与数据相关的标记和颜色的3D散点图

      2024-09-25 10:15:01
      python , 编程开发
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5245777

      查看更多

      最新文章

      图的存储

      2024-11-06 07:24:46

      R语言文本挖掘tf-idf,主题建模,情感分析,n-gram建模研究|附代码数据

      2024-09-25 10:15:32

      Python使用神经网络进行简单文本分类

      2024-09-25 10:15:32

      Python3 - 时间处理与定时任务

      2024-09-25 10:15:32

      SpringCloud-技术专区-Gateway基于OAuth2.0 的身份认证

      2024-09-25 10:15:32

      Python实战技巧(9)Python发送邮件

      2024-09-25 10:15:32

      查看更多

      热门文章

      Java学习之算术运算符两只老虎

      2023-04-19 09:23:13

      Lambda函数

      2023-02-08 10:33:56

      R语言方差分析(ANOVA)学生参加辅导课考试成绩差异

      2023-02-08 10:33:55

      r语言中对LASSO,Ridge岭回归和Elastic Net模型实现

      2023-02-10 10:10:49

      通过SAS网络分析对人口迁移进行可视化分析

      2023-02-08 10:33:55

      R语言多分类logistic逻辑回归模型在混合分布模拟个人风险损失值评估的应用

      2023-02-10 05:50:40

      查看更多

      热门标签

      java Java python 编程开发 代码 开发语言 算法 线程 Python html 数组 C++ 元素 javascript c++
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      C#创建Windows窗体应用程序实例2【学生管理信息系统】

      如何处理用代码创建SD Sales order时遇到的错误消息KI 180

      Java 项目前端项目调定时任务

      java实现人脸识别源码【含测试效果图】——Dao层(BaseDao)

      数组的降序排序 java

      呵呵,JavaScript 真好玩(苦笑脸)

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号