Koltin实现动态心率曲线

用MPAndroid 实现动态的心率曲线

废话不多说,先上图点击开始就可以实现自动心电图,同时可以暂停可继续开始
在这里插入图片描述上面是实现效果,由于是第一次上传图片,不会发动图,目前就两张图片,

  1. 首先是集成mpchart Android,具体集成方式请直接百度就好
  2. 先实现y轴的代码,相关参数设计如下:
leftAxis?.let {
            //是否绘制轴线
            it.setDrawAxisLine(true)
            //设置轴线的颜色
            it.axisLineColor = context!!.resources.getColor(R.color.color_f3f3f3)
            //是否绘制网格线
            it.setDrawGridLines(true) //横的线(与Y轴有关)
            //y轴的线为虚线
            //leftAxis.enableGridDashedLine(10f, 5f, 0f);
            it.gridLineWidth = gridLineWidth
            //设置网格线的颜色
            it.gridColor = context!!.resources.getColor(R.color.color_f3f3f3)
            it.textSize = axisYTextSize
            it.textColor = axisTextColor
            //leftAxis.setSpaceMin(20);
            //leftAxis.setSpaceMax(20);
            //字体距离曲线的位置
            it.xOffset = 6f
            it.yOffset = 0f
            //设置最大值和最小值
            it.axisMinimum = Y_MIN
            it.axisMaximum = Y_MAX
            //y轴坐标点个数
            it.labelCount = yAxisLabelCount

            it.valueFormatter = StepYaxisValueFormat()
        }
        ///右边的y轴///
        rightAxis?.let {
            it.isEnabled = false
            // it.setDrawAxisLine(false)
            // it.spaceMax = 0f
        }

这里主要是把左边和右边的轴线,显示为不显示,如果需要显示请把 isEnable设置为true,即可

3.接下来是x轴的相关参数的设置:

   xAxis?.let {
            //是否绘制网格线
            it.setDrawGridLines(true) //竖的线(与X轴有关)
            //网格线的宽度
            it.gridLineWidth = gridLineWidth
            //网格颜色
            it.gridColor = context!!.resources.getColor(R.color.color_f3f3f3)
            //字体距离曲线的位置
            it.yOffset = 0f
            it.xOffset = 0f
            it.position = XAxis.XAxisPosition.BOTTOM // 设置X轴的位置
            it.setDrawAxisLine(true) //是否显示X轴
            //轴线的颜色
            it.axisLineColor = context!!.resources.getColor(R.color.color_f3f3f3)
            it.textSize = axisXTextSize
            it.textColor = axisTextColor
            //xAxis.setSpaceMin(5);//小于最小值5开始画
            it.spaceMax = 0f //大于最大值10
            it.axisMinimum = 0f //x轴显示的最小值

            //只有不是实时曲线的时候才设置这个值
            // it.axisMaximum = xAxisVisibleValueRange //x轴显示的最大值

            //xAxis.mAxisRange=2f;
            it.setLabelCount(xAxisLabelCount, false)
            it.valueFormatter = StepXAxisValueFormat()
        }

相同的道理,这里是将x轴的相关方法设置为不显示,具体的参数意思,在代码中已经有了注释,到这里我们完成了,相关设置

4.接下来是实现linechart的曲线属性相关设置;

 /**
     * 
     *
     * @return void
     * @time 2021-9-16 17:06:04
     */
    private fun buildOxDataSet(entries: List<Entry>, label: String): LineDataSet {
       
        val oxDataSet = LineDataSet(entries, label)
        oxDataSet.lineWidth = lineWidth
        oxDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER //设置为贝塞尔曲线
        oxDataSet.setDrawValues(false) //不显示数值
        oxDataSet.setDrawCircles(false) //不显示圆点
        // 设置高亮十字光标线的虚化:设置第二个参数为虚线间隔
        oxDataSet.enableDashedHighlightLine(10f, 0f, 0f)
        // 设置十字光标线的颜色
        oxDataSet.isHighlightEnabled = true //显示高亮
        oxDataSet.highLightColor = highLightColor
        oxDataSet.setDrawHorizontalHighlightIndicator(false) //水平的高亮线不绘制
        //设置原点的颜色
        oxDataSet.circleRadius = 2.0f
        //oxDataSet.setDrawCircles(true);
        oxDataSet.circleHoleRadius = 2.0f
        oxDataSet.setCircleColor(context!!.resources.getColor(R.color.color_ff4900))
        oxDataSet.color = lineColor
        //是否填充
        oxDataSet.setDrawFilled(true)
        oxDataSet.fillDrawable = context!!.resources.getDrawable(R.drawable.gradient_ecg_line)
        return oxDataSet
    }

这里就不做过多介绍了,属性参数的意思都有注释,如果需要改线条的颜色或者粗细,只用修改对应的属性值就好了

5.最后就是动态添加数据环节,代码如下:

 /**
     * 动态增加折线数据
     *
     * @param entries 折线的数据
     * @return void
     * @time 2019-10-16 15:07:53
     */
    fun addEntry(entries: ArrayList<Entry>) {
        if (null == ecgDataSet) {
//            realTimeList.clear()
//            realTimeList.addAll(entries)
            ecgDataSet = buildOXDataSet(entries)
            (lineDataSets as ArrayList).add(ecgDataSet!!)
        } else {
            val lineDataSet = lineData!!.getDataSetByLabel(
                LABEL_ECG,
                true
            ) as LineDataSet
//            realTimeList.addAll(entries)
//            lineDataSet.entries = realTimeList
            //changeLineStatues(lineDataSet);
            for (entry in entries) {
                lineDataSet.addEntry(entry)
            }
        }
        val entry = entries[entries.size - 1]
        //设置上面的limitline动态增加
        val lineDataSet = lineData!!.getDataSetByLabel(LABEL_LIMIT_LINE_UP, true)
        if (lineDataSet.entryCount >= 2 && entry.x > xAxisVisibleValueRange) {
            lineDataSet.removeEntry(lineDataSet.entryCount - 1)
            lineDataSet.addEntry(Entry(entry.x, LIMIT_VALUE_MAX))
        }
        lineData!!.notifyDataChanged()
        lineChart!!.notifyDataSetChanged()
        //控制x轴值的显示范围
        lineChart!!.setVisibleXRangeMaximum(xAxisVisibleValueRange)
        if (entry.x > xAxisVisibleValueRange) {
            lineChart!!.moveViewToX(entry.x) //移动到最后一个
        } else {
            lineChart!!.moveViewToX(0f)
        }
    }

这里主要是通过getDataSetByLabel()函数去获取linechart中已经有的曲线的linedataset,同时把获取的数据添加到对应的linedataset里面,同时将视图拉向最后一个点的x轴最大值,要实现动态的,必须设置x轴的最大视图范围,通过函数名:setVisibleXRangeMaximum()去设置。以上就是动态实现心率的相关代码

6.最后贴出全部的代码:

/**
 * @ClassName EcgChartHelper
 * @Description TODO
 * @Author  Darcy
 * @Date 2021/9/17 16:44
 * @Version 1.0
 */
class EcgChartHelper(chart: LineChart, context: Context) {

    private var xAxis: XAxis? = null
    private var leftAxis: YAxis? = null
    private var rightAxis: YAxis? = null
    private var context: Context? = context
    private var lineChart: LineChart? = chart

    //高亮线的颜色
    private val highLightColor = -0x3e3717

    //网格线宽度
    private val gridLineWidth = 1.0f

    //Y坐标轴刻度文字大小
    private val axisYTextSize = 10f

    //X坐标轴刻度文字大小
    private val axisXTextSize = 8f

    //坐标轴刻度文字颜色
    private val axisTextColor = -0x5c5c5d
    private val Y_MAX = 120f //正常范围边界最大值
    private val Y_MIN = 70f //正常范围边界最小值
    private val yAxisLabelCount = 20 //y轴刻度数

    // x轴显示的值范围大小,
    private val xAxisVisibleValueRange = 300.0f

    private val LABEL_LIMIT_LINE_UP = "limit_line_up"

    //有效值(灰色区域)
    private val LIMIT_VALUE_MIN = 90f //有效范围的最小值

    private val LIMIT_VALUE_MAX = 100f //有效范围的最大值

    //灰色区域最大值
    private val maxRangeVaule = 300.0f

    //灰色区域颜色值
    private val limitAreaColor = -0xdf243a

    private val LABEL_ECG = "label_ecg"

    //X轴的刻度数,
    private val xAxisLabelCount = 60

    //线宽
    private val lineWidth = 1.0f

    //private val lineColor: Int =  -0x7f006800
    private val lineColor: Int = -0x5bd00


    //设置灰色区域(有效的范围值)
    private fun bulidLimitArea() {
        //灰色区域绘制
        val dataSet: LineDataSet = buildUpLimitDataSet()
        (lineDataSets as ArrayList).add(dataSet)
        //添加一个 LineData
        lineData = LineData(lineDataSets)
        lineChart!!.data = lineData
        lineChart!!.invalidate()
    }

    /**
     * 设置限制线.基线(预警线的线条)
     *
     * @return void
     * @time 2020-7-30 18:09:16
     */
    private fun buildUpLimitDataSet(): LineDataSet {
        val limitLineWidth = 0.1f
        val entries: ArrayList<Entry> = ArrayList()
        entries.add(Entry(0f, LIMIT_VALUE_MAX))
        entries.add(Entry(maxRangeVaule, LIMIT_VALUE_MAX))
        val dataSet = LineDataSet(entries, LABEL_LIMIT_LINE_UP)
        dataSet.lineWidth = limitLineWidth
        dataSet.mode = LineDataSet.Mode.LINEAR //
        dataSet.setDrawValues(false) //不显示数值
        dataSet.setDrawCircles(false) //不显示圆点
        dataSet.isHighlightEnabled = false
        dataSet.setDrawFilled(true)
        dataSet.fillFormatter = LimitLineFillFormatter(LIMIT_VALUE_MIN)
        dataSet.fillColor = limitAreaColor
        dataSet.color = -0x111112
        dataSet.fillAlpha = 0x1a

        return dataSet
    }

    /**
     * Y坐标轴设置
     *
     * @return void
     * @time 2021-9-16 16:25:46
     */
    private fun initYAxis() {
        leftAxis?.let {
            //是否绘制轴线
            it.setDrawAxisLine(true)
            //设置轴线的颜色
            it.axisLineColor = context!!.resources.getColor(R.color.color_f3f3f3)
            //是否绘制网格线
            it.setDrawGridLines(true) //横的线(与Y轴有关)
            //y轴的线为虚线
            //leftAxis.enableGridDashedLine(10f, 5f, 0f);
            it.gridLineWidth = gridLineWidth
            //设置网格线的颜色
            it.gridColor = context!!.resources.getColor(R.color.color_f3f3f3)
            it.textSize = axisYTextSize
            it.textColor = axisTextColor
            //leftAxis.setSpaceMin(20);
            //leftAxis.setSpaceMax(20);
            //字体距离曲线的位置
            it.xOffset = 6f
            it.yOffset = 0f
            //设置最大值和最小值
            it.axisMinimum = Y_MIN
            it.axisMaximum = Y_MAX
            //y轴坐标点个数
            it.labelCount = yAxisLabelCount

            it.valueFormatter = StepYaxisValueFormat()
        }
        ///右边的y轴///
        rightAxis?.let {
            it.isEnabled = false
            // it.setDrawAxisLine(false)
            // it.spaceMax = 0f
        }
    }

    /**
     * X坐标轴设置
     *
     * @return void
     * @time 2020-7-30 18:09:24
     */
    private fun initXAxis() {
        xAxis?.let {
            //是否绘制网格线
            it.setDrawGridLines(true) //竖的线(与X轴有关)
            //网格线的宽度
            it.gridLineWidth = gridLineWidth
            //网格颜色
            it.gridColor = context!!.resources.getColor(R.color.color_f3f3f3)
            //字体距离曲线的位置
            it.yOffset = 0f
            it.xOffset = 0f
            it.position = XAxis.XAxisPosition.BOTTOM // 设置X轴的位置
            it.setDrawAxisLine(true) //是否显示X轴
            //轴线的颜色
            it.axisLineColor = context!!.resources.getColor(R.color.color_f3f3f3)
            it.textSize = axisXTextSize
            it.textColor = axisTextColor
            //xAxis.setSpaceMin(5);//小于最小值5开始画
            it.spaceMax = 0f //大于最大值10
            it.axisMinimum = 0f //x轴显示的最小值

            //只有不是实时曲线的时候才设置这个值
            // it.axisMaximum = xAxisVisibleValueRange //x轴显示的最大值

            //xAxis.mAxisRange=2f;
            it.setLabelCount(xAxisLabelCount, false)
            it.valueFormatter = StepXAxisValueFormat()
        }

    }

    /**
     * 图表LineChart设置
     *
     * @return void
     * @time 2020-7-30 18:09:20
     */
    private fun initLineChart() {
        lineChart?.let {
            /*图表设置***/
            it.setTouchEnabled(true) // 设置是否可以触摸
            //是否启用chart绘图区后面的背景矩形将绘制
            it.setDrawGridBackground(false)
            //        //设置网格背景应与绘制的颜色
            it.setGridBackgroundColor(-0x1)
            //设置markView
//        TempMarkView myMarkerView = new TempMarkView(context);
//        myMarkerView.setChartView(lineChart);
//        lineChart.setMarker(myMarkerView);
            //启用/禁用绘制图表边框(chart周围的线)。
            it.setDrawBorders(false)
            //是否可以拖动
            it.isDragEnabled = true
            //启用/禁用缩放图表上的两个轴
            it.setScaleEnabled(false)
            //设置在曲线图中显示的最大数量
//        vMutlilineChart.setVisibleXRangeMaximum(40);//可视范围的值的范围
            it.setNoDataText("")
            val description = Description()
            description.isEnabled = false
            description.text = "" //我是描述信息
            it.description = description
            //是否显示高亮线,十字线条
            it.isHighlightPerTapEnabled = false
            it.isHighlightPerDragEnabled = false
            val legend: Legend = it.legend
            //legend.setWordWrapEnabled(false);//设置标签是否换行(当多条标签时 需要换行显示、如上右图)true:可换行。false:不换行
            legend.isEnabled = false //隐藏图例
        }
    }

    /**
     * 计步的折线图
     *
     * @return void
     * @time 2021-9-16 17:06:17
     */
    private fun buildOXDataSet(entries: List<Entry>): LineDataSet? {
        return buildOxDataSet(entries, LABEL_ECG)
    }

    /**
     * 计步的折线图
     *
     * @return void
     * @time 2021-9-16 17:06:04
     */
    private fun buildOxDataSet(entries: List<Entry>, label: String): LineDataSet {
        //温度曲线设置
        val oxDataSet = LineDataSet(entries, label)
        oxDataSet.lineWidth = lineWidth
        oxDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER //设置为贝塞尔曲线
        oxDataSet.setDrawValues(false) //不显示数值
        oxDataSet.setDrawCircles(false) //不显示圆点
        // 设置高亮十字光标线的虚化:设置第二个参数为虚线间隔
        oxDataSet.enableDashedHighlightLine(10f, 0f, 0f)
        // 设置十字光标线的颜色
        oxDataSet.isHighlightEnabled = true //显示高亮
        oxDataSet.highLightColor = highLightColor
        oxDataSet.setDrawHorizontalHighlightIndicator(false) //水平的高亮线不绘制
        //设置原点的颜色
        oxDataSet.circleRadius = 2.0f
        //oxDataSet.setDrawCircles(true);
        oxDataSet.circleHoleRadius = 2.0f
        oxDataSet.setCircleColor(context!!.resources.getColor(R.color.color_ff4900))
        oxDataSet.color = lineColor
        //是否填充
        oxDataSet.setDrawFilled(true)
        oxDataSet.fillDrawable = context!!.resources.getDrawable(R.drawable.gradient_ecg_line)
        return oxDataSet
    }

    private var ecgDataSet: LineDataSet? = null
    private val lineDataSets: List<LineDataSet> = ArrayList()
    private var lineData: LineData? = null

    /**
     * 添加数据
     *
     * @param entries 折线的数据
     * @return void
     * @time 2021-9-16 17:08:48
     */
    fun addEntries(entries: ArrayList<Entry>) {
        //先清除存在的点
        lineChart!!.clearValues()
        ecgDataSet = buildOXDataSet(entries)
        (lineDataSets as ArrayList).add(ecgDataSet!!)
        //控制网格不变
        if (entries.isNotEmpty() && entries[entries.size - 1].x > xAxisVisibleValueRange) {
            xAxis!!.spaceMax = 0f
        } else {
            val max =
                if (entries.size == 0) xAxisVisibleValueRange else xAxisVisibleValueRange - entries[entries.size - 1].x
            xAxis!!.spaceMax = max
        }
        lineData?.notifyDataChanged()
        lineChart!!.notifyDataSetChanged()
        lineChart!!.setVisibleXRangeMinimum(xAxisVisibleValueRange)
        //lineChart!!.moveViewToX(entries.size.toFloat())
    }

    /**
     * 动态增加折线数据
     *
     * @param xValue x轴对应的值
     * @param yValue y轴对应的值
     * @return void
     * @time 2020-8-24 15:55:08
     */
    fun addEntry(xValue: Float, yValue: Float) {
        addEntry(Entry(xValue, yValue))
    }

    /**
     * 动态增加折线数据
     *
     * @param entry 折线的数据
     * @return void
     * @time 2020-8-24 15:55:11
     */
    fun addEntry(entry: Entry) {
        val entries = java.util.ArrayList<Entry>()
        entries.add(entry)
        addEntry(entries)
    }


    var realTimeList: ArrayList<Entry> = ArrayList()

    /**
     * 动态增加折线数据
     *
     * @param entries 折线的数据
     * @return void
     * @time 2019-10-16 15:07:53
     */
    fun addEntry(entries: ArrayList<Entry>) {
        if (null == ecgDataSet) {
//            realTimeList.clear()
//            realTimeList.addAll(entries)
            ecgDataSet = buildOXDataSet(entries)
            (lineDataSets as ArrayList).add(ecgDataSet!!)
        } else {
            val lineDataSet = lineData!!.getDataSetByLabel(
                LABEL_ECG,
                true
            ) as LineDataSet
//            realTimeList.addAll(entries)
//            lineDataSet.entries = realTimeList
            //changeLineStatues(lineDataSet);
            for (entry in entries) {
                lineDataSet.addEntry(entry)
            }
        }
        val entry = entries[entries.size - 1]
        //设置上面的limitline动态增加
        val lineDataSet = lineData!!.getDataSetByLabel(LABEL_LIMIT_LINE_UP, true)
        if (lineDataSet.entryCount >= 2 && entry.x > xAxisVisibleValueRange) {
            lineDataSet.removeEntry(lineDataSet.entryCount - 1)
            lineDataSet.addEntry(Entry(entry.x, LIMIT_VALUE_MAX))
        }
        lineData!!.notifyDataChanged()
        lineChart!!.notifyDataSetChanged()
        //控制x轴值的显示范围
        lineChart!!.setVisibleXRangeMaximum(xAxisVisibleValueRange)
        if (entry.x > xAxisVisibleValueRange) {
            lineChart!!.moveViewToX(entry.x) //移动到最后一个
        } else {
            lineChart!!.moveViewToX(0f)
        }
    }

    fun clearData() {
        if (lineChart!!.data != null) lineChart!!.clearValues()
        //置空保存的横坐标数据
        //setRealXvalue(null)
        initLineChart()
        initYAxis()
        bulidLimitArea()
        //initLineDatas()
        initXAxis()
        lineData!!.notifyDataChanged()
        lineChart!!.notifyDataSetChanged()
    }

    init {
        xAxis = chart.xAxis
        leftAxis = chart.axisLeft
        rightAxis = chart.axisRight
        initLineChart()
        initXAxis()
        initYAxis()
        bulidLimitArea()
    }
}

以上是动态实现心率曲线的全部代码。由于是公司的项目,在这里就不放源码了,有了这个helper类,直接引入调用就好了。

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
QCustomPlot是一个C++类库,可以让用户在Qt应用程序中绘制各种各样的图表,包括曲线图。下面是一些步骤和代码示例来绘制一个简单的曲线图。 首先,您需要安装QCustomPlot库。您可以通过以下命令将其添加到Qt项目中: ``` QT += widgets LIBS += -L/path/to/qcustomplot -lqcustomplot ``` 然后,在您的项目中创建一个QCustomPlot实例,并为X轴和Y轴添加标签和范围: ``` #include "qcustomplot.h" QCustomPlot *plot = new QCustomPlot(this); plot->xAxis->setLabel("时间"); plot->yAxis->setLabel(""); plot->xAxis->setRange(0, 10); plot->yAxis->setRange(50, 100); ``` 接下来,您需要创建一个QVector,用于存储曲线的数据点。在此示例中,我们将模拟这些数据: ``` QVector<QCPGraphData> heartRateData; for (int i = 0; i <= 100; ++i) { QCPGraphData dataPoint(i, 70 + qSin(i / 10.0) * 15); heartRateData.append(dataPoint); } ``` 现在,您可以将数据添加到图表中并为其设置样式: ``` QCPGraph *heartRateGraph = plot->addGraph(); heartRateGraph->setData(heartRateData); heartRateGraph->setPen(QPen(Qt::red)); heartRateGraph->setLineStyle(QCPGraph::lsLine); ``` 最后,您需要将图表添加到Qt布局中,并在需要时进行更新: ``` QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(plot); // Update data and replot the graph heartRateData[50].value = 90; heartRateGraph->setData(heartRateData); plot->replot(); ``` 通过这些步骤,您可以轻松地创建一个简单的曲线图。当然,您可以根据自己的需要添加更多的特性和样式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值