1. 程式人生 > >QT QCharts QScatterSeries 空心點陣圖,滑鼠移動到上面顯示數值,滑鼠移開數值消失

QT QCharts QScatterSeries 空心點陣圖,滑鼠移動到上面顯示數值,滑鼠移開數值消失

在最近接到的需求是這樣的,畫一個折線圖,關鍵點使用空心的圓點標識出來,滑鼠移動到關鍵點上,顯示出當前數值;滑鼠移走數值消失。

我們遇到這個需求的時候,第一時間就會想到使用 QLineSeries 畫折線圖。首先初始化

    QChart *chart = new QChart();
    chart->legend()->setVisible(false);
    ui->chartView->setChart(chart);
    ui->chartView->setRenderHint(QPainter::Antialiasing);

    chart->setBackgroundBrush(QBrush(QColor(248, 251, 255)));

將每個點新增到QLineSeries序列中。然後就會形成折線圖。如下:

    QChart *chart = ui->chartView->chart();
    chart->removeAllSeries();
    chart->removeAxis(chart->axisX());
    chart->removeAxis(chart->axisY());

    //折線圖
    QLineSeries *series0 = new QLineSeries();

    QPen pen;
    pen.setStyle(Qt::SolidLine);
    pen.setWidth(4);
    pen.setColor(QColor(21, 100, 255));
    series0->setPen(pen);//折現序列的線條設定
    QLineSeries *series0 = (QLineSeries *)ui->chartView->chart()->series().at(0);

    series0->clear();

    qsrand(QTime::currentTime().second());

    qreal t=0, y1, intv=1;
    qreal rd;
    int cnt=16;
    for (int i=0; i<cnt; i++)
    {
        rd = (qrand() % 100);
        y1=rd;
        series0->append(t, y1);
        t+=intv;
    }

這是完成了第一步,畫出來了折線圖。但是對於那些圓點要顯示出來的話我們可以考慮使用QScatterSeries來畫一些離散的點。

    QScatterSeries *series1 = new QScatterSeries();
    series1->setMarkerShape(QScatterSeries::MarkerShapeCircle);//圓形的點
    series1->setBorderColor(QColor(21, 100, 255)); //離散點邊框顏色
    series1->setBrush(QBrush(QColor(21, 100, 255)));//離散點背景色
    series1->setMarkerSize(12); //離散點大小
    QLineSeries *series0 = (QLineSeries *)ui->chartView->chart()->series().at(0);
    QScatterSeries *series1 = (QScatterSeries *)ui->chartView->chart()->series().at(1);

    series0->clear();
    series1->clear();

    qsrand(QTime::currentTime().second());

    qreal t=0, y1, intv=1;
    qreal rd;
    int cnt=16;
    for (int i=0; i<cnt; i++)
    {
        rd = (qrand() % 100);
        y1=rd;
        series0->append(t, y1);
        series1->append(t, y1);

        t+=intv;
    }

然後我們添加了一些離散的點,效果如下圖:

很顯然,雖然添加了離散的圓形的點,但是並沒有滿足我們的需求,因為需求是空心的圓點。而且控制元件也沒提供相關函式可以設定成空心。但是這裡面有3個函式值得注意

    series1->setBorderColor(QColor(21, 100, 255)); //離散點邊框顏色
    series1->setBrush(QBrush(QColor(21, 100, 255)));//離散點背景色
    series1->setMarkerSize(12); //離散點大小

因為可以設定一個點的大小,邊框和顏色。那我們如果想實現一個空心的離散點就可以這樣做:

以同一個位置為圓心,畫兩個半徑不同的實心圓。下面的圓半徑大,顏色就是邊框的顏色藍色;上面的圓形半徑小,顏色設定為白色。這樣兩個圓形疊加起來的效果,視覺上就是一個空心的圓形。按照這個思路,我們需要使用2個QScatterSeries序列

series0 : 半徑較大,背景為藍色,充當邊框。

series1:半徑較小,北京為白色,充電圓心。

    //散點圖(用於邊框)
    QScatterSeries *series1 = new QScatterSeries();
    series1->setMarkerShape(QScatterSeries::MarkerShapeCircle);//圓形的點
    series1->setBorderColor(QColor(21, 100, 255));  //邊框顏色
    series1->setBrush(QBrush(QColor(21, 100, 255)));//背景顏色
    series1->setMarkerSize(12);                     //點大小

    //散點圖(用於中心)
    QScatterSeries *series2 = new QScatterSeries();
    series2->setMarkerShape(QScatterSeries::MarkerShapeCircle);//圓形的點
    series2->setBorderColor(Qt::white);//邊框顏色
    series2->setBrush(QBrush(Qt::white));//背景顏色
    series2->setMarkerSize(6);//點大小

    chart->addSeries(series1);
    chart->addSeries(series2);
    QLineSeries *series0 = (QLineSeries *)ui->chartView->chart()->series().at(0);
    QScatterSeries *series1 = (QScatterSeries *)ui->chartView->chart()->series().at(1);
    QScatterSeries *series2 = (QScatterSeries *)ui->chartView->chart()->series().at(2);

    series0->clear();
    series1->clear();
    series2->clear();

    qsrand(QTime::currentTime().second());

    qreal t=0, y1, intv=1;
    qreal rd;
    int cnt=16;
    for (int i=0; i<cnt; i++)
    {
        rd = (qrand() % 100);
        y1=rd;
        series0->append(t, y1);
        series1->append(t, y1);
        series2->append(t, y1);

        t+=intv;
    }

效果如下:

做完這些,我們還有最後一個需求就是滑鼠移動到這些離散的點上,要顯示出當前點的數值。由於框架並沒有提供相關的api,所以我們要自己完成這項工作。我們可以想象,顯示的數值需要使用QLabel承載,當滑鼠移動到這些點上,QLabel就show,移開就hide。那麼怎麼確定滑鼠是否移動到這些離散點上呢?查閱文件,我們發現QCatterSeries有這樣一個訊號

他的意思就是,這是一個訊號,當滑鼠移動到上面,或者從上面移開就會發射這個訊號,其中point是移動到哪個點上,當移動到上面,state=true;否則state就為false。

我們可以連線這個訊號到我們自己的槽函式

connect(series2, &QScatterSeries::hovered, this, &TDMTrendChartForm::slotPointHoverd);//用於滑鼠移動到點上顯示數值
void TDMTrendChartForm::slotPointHoverd(const QPointF &point, bool state)
{
    if (state) {
        m_valueLabel->setText(QString::asprintf("%1.0f%", point.y()));

        QPoint curPos = mapFromGlobal(QCursor::pos());
        m_valueLabel->move(curPos.x() - m_valueLabel->width() / 2, curPos.y() - m_valueLabel->height() * 1.5);//移動數值

        m_valueLabel->show();//顯示出來
    }
    else
        m_valueLabel->hide();//進行隱藏

}

======================================================================================

======================================================================================